Generate HTML Documentation in Suggestion Entries (https://github.com/enso-org/ide/pull/686)

Modifies docstring from suggestion database to HTML code, enabling us to present 
documentation for nodes in searcher

Original commit: 60b32d2956
This commit is contained in:
Maciej Mikołajek 2020-07-27 18:52:24 +02:00 committed by GitHub
parent 9c52ff9db6
commit 4874c71ef6
4 changed files with 70 additions and 38 deletions

View File

@ -61,12 +61,12 @@ extern "C" {
pub struct Client {}
impl Client {
/// Creates a `Client`
/// Creates a `Client`.
pub fn new() -> Result<Client> {
Ok(Client {})
}
/// Parses Enso code with JS-based parser
/// Parses Enso code with JS-based parser.
pub fn parse(&self, program:String, ids:IdMap) -> api::Result<Ast> {
let ast = || {
let json_ids = serde_json::to_string(&ids)?;
@ -77,7 +77,7 @@ impl Client {
Ok(ast()?)
}
/// Parses Enso code with metadata
/// Parses Enso code with metadata.
pub fn parse_with_metadata<M:api::Metadata>
(&self, program:String) -> api::Result<api::ParsedSourceFile<M>> {
let result = || {
@ -88,7 +88,7 @@ impl Client {
Ok(result()?)
}
/// Calls JS doc parser to generate HTML from documented Enso code
/// Calls JS doc parser to generate HTML from documented Enso code.
pub fn generate_html_docs(&self, program:String) -> api::Result<String> {
let html_code = || {
let html_code = doc_parser_generate_html_source(program)?;
@ -97,7 +97,7 @@ impl Client {
Ok(html_code()?)
}
/// Calls JS doc parser to generate HTML from pure doc code w/o Enso's AST
/// Calls JS doc parser to generate HTML from pure doc code without Enso's AST.
pub fn generate_html_doc_pure(&self, code:String) -> api::Result<String> {
let html_code = || {
let html_code = doc_parser_generate_html_from_doc(code)?;

View File

@ -165,7 +165,7 @@ impl DocParser {
}
/// Parses pure documentation code and generates HTML code.
/// Will return empty string for empty entry
/// Will return empty string for empty entry.
pub fn generate_html_doc_pure(&self, code:String) -> api::Result<String> {
self.borrow_mut().generate_html_doc_pure(code)
}

View File

@ -227,7 +227,7 @@ impl Client {
Ok(client)
}
/// Sends a request to parser service to parse Enso code
/// Sends a request to parser service to parse Enso code.
pub fn parse(&mut self, program:String, ids:IdMap) -> api::Result<Ast> {
let request = Request::ParseRequest {program,ids};
let response = self.rpc_call::<serde_json::Value>(request)?;
@ -237,7 +237,7 @@ impl Client {
}
}
/// Sends a request to parser service to parse code with metadata
/// Sends a request to parser service to parse code with metadata.
pub fn parse_with_metadata<M:Metadata>
(&mut self, program:String) -> api::Result<ParsedSourceFile<M>> {
let request = Request::ParseRequestWithMetadata {content:program};
@ -248,7 +248,7 @@ impl Client {
}
}
/// Sends a request to parser service to generate HTML code from documented Enso code
/// Sends a request to parser service to generate HTML code from documented Enso code.
pub fn generate_html_docs(&mut self, program:String) -> api::Result<String> {
let request = Request::DocParserGenerateHtmlSource {program};
let response_doc = self.rpc_call_doc(request)?;
@ -258,7 +258,7 @@ impl Client {
}
}
/// Sends a request to parser service to generate HTML code from pure documentation code
/// Sends a request to parser service to generate HTML code from pure documentation code.
pub fn generate_html_doc_pure(&mut self, code:String) -> api::Result<String> {
let request = Request::DocParserGenerateHtmlFromDoc {code};
let response_doc = self.rpc_call_doc(request)?;

View File

@ -7,6 +7,7 @@ use crate::double_representation::module::QualifiedName;
use enso_protocol::language_server;
use language_server::types::SuggestionsDatabaseVersion;
use language_server::types::SuggestionDatabaseUpdatesEvent;
use parser::DocParser;
pub use language_server::types::SuggestionEntryArgument as Argument;
pub use language_server::types::SuggestionEntryId as EntryId;
@ -46,36 +47,46 @@ pub struct Entry {
impl Entry {
/// Create entry from the structure deserialized from the Language Server responses.
pub fn from_ls_entry(entry:language_server::types::SuggestionEntry) -> FallibleResult<Self> {
pub fn from_ls_entry(entry:language_server::types::SuggestionEntry, logger:impl AnyLogger)
-> FallibleResult<Self> {
use language_server::types::SuggestionEntry::*;
let convert_doc = |doc: Option<String>| doc.and_then(|doc| match Entry::gen_doc(doc) {
Ok(d) => Some(d),
Err(err) => {
error!(logger,"Doc parser error: {err}");
None
},
});
let this = match entry {
Atom {name,module,arguments,return_type,documentation} => Self {
name,arguments,return_type,documentation,
module : module.try_into()?,
self_type : None,
kind : EntryKind::Atom,
},
name,arguments,return_type,
module : module.try_into()?,
self_type : None,
documentation : convert_doc(documentation),
kind : EntryKind::Atom,
},
Method {name,module,arguments,self_type,return_type,documentation} => Self {
name,arguments,return_type,documentation,
module : module.try_into()?,
self_type : Some(self_type),
kind : EntryKind::Method,
},
name,arguments,return_type,
module : module.try_into()?,
self_type : Some(self_type),
documentation : convert_doc(documentation),
kind : EntryKind::Method,
},
Function {name,module,arguments,return_type,..} => Self {
name,arguments,return_type,
module : module.try_into()?,
self_type : None,
documentation : default(),
kind : EntryKind::Function,
},
name,arguments,return_type,
module : module.try_into()?,
self_type : None,
documentation : default(),
kind : EntryKind::Function,
},
Local {name,module,return_type,..} => Self {
name,return_type,
arguments : default(),
module : module.try_into()?,
self_type : None,
documentation : default(),
kind : EntryKind::Local,
},
name,return_type,
arguments : default(),
module : module.try_into()?,
self_type : None,
documentation : default(),
kind : EntryKind::Local,
},
};
Ok(this)
}
@ -96,12 +107,20 @@ impl Entry {
pub fn with_name(self, name:impl Into<String>) -> Self {
Self {name:name.into(),..self}
}
/// Generates HTML documentation for documented suggestion.
fn gen_doc(doc: String) -> FallibleResult<String> {
let parser = DocParser::new()?;
let output = parser.generate_html_doc_pure(doc);
Ok(output?)
}
}
impl TryFrom<language_server::types::SuggestionEntry> for Entry {
type Error = failure::Error;
fn try_from(entry:language_server::types::SuggestionEntry) -> FallibleResult<Self> {
Self::from_ls_entry(entry)
let logger = Logger::new("SuggestionEntry");
Self::from_ls_entry(entry, logger)
}
}
@ -138,7 +157,8 @@ impl SuggestionDatabase {
let mut entries = HashMap::new();
for ls_entry in response.entries {
let id = ls_entry.id;
match Entry::from_ls_entry(ls_entry.suggestion) {
let logger_entry = Logger::new("SuggestionEntry");
match Entry::from_ls_entry(ls_entry.suggestion, logger_entry) {
Ok(entry) => { entries.insert(id, Rc::new(entry)); },
Err(err) => { error!(logger,"Discarded invalid entry {id}: {err}"); },
}
@ -208,6 +228,12 @@ mod test {
use super::*;
use enso_protocol::language_server::SuggestionsDatabaseEntry;
use wasm_bindgen_test::wasm_bindgen_test_configure;
use wasm_bindgen_test::wasm_bindgen_test;
wasm_bindgen_test_configure!(run_in_browser);
@ -240,7 +266,7 @@ mod test {
assert_eq!(module_method_entry.code_to_insert(), "Main.moduleMethod".to_string());
}
#[test]
#[wasm_bindgen_test]
fn initialize_database() {
// Empty db
let response = language_server::response::GetSuggestionDatabase {
@ -257,7 +283,7 @@ mod test {
module : "TestProject.TestModule".to_string(),
arguments : vec![],
return_type : "TestAtom".to_string(),
documentation : None
documentation : Some("Test *Atom*".to_string())
};
let db_entry = SuggestionsDatabaseEntry {id:12, suggestion:entry};
let response = language_server::response::GetSuggestionDatabase {
@ -265,8 +291,14 @@ mod test {
current_version : 456
};
let db = SuggestionDatabase::from_ls_response(response);
let response_doc =
"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html\" charset=\"UTF-8\" \
/><link rel=\"stylesheet\" href=\"style.css\" /><title></title></head><body><div class=\
\"Doc\"><div class=\"Synopsis\"><div class=\"Raw\">Test <b>Atom</b></div></div></div>\
</body></html>";
assert_eq!(db.entries.borrow().len(), 1);
assert_eq!(*db.get(12).unwrap().name, "TextAtom".to_string());
assert_eq!(db.get(12).unwrap().documentation, Some(response_doc.to_string()));
assert_eq!(db.version.get(), 456);
}