Skip to content

More demo functionality #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 87 additions & 5 deletions wasm-demo/src/conv.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::return_types;
use ra_ide_api::{
CompletionItem, CompletionItemKind, FileId, FilePosition, InsertTextFormat, LineCol, LineIndex,
CompletionItem, CompletionItemKind, Documentation, FileId, FilePosition, FunctionSignature,
InsertTextFormat, LineCol, LineIndex, NavigationTarget, RangeInfo, Severity,
};
use ra_syntax::TextRange;
use ra_text_edit::AtomTextEdit;
Expand Down Expand Up @@ -50,7 +51,7 @@ impl ConvWith<&LineIndex> for TextRange {
impl Conv for CompletionItemKind {
type Output = return_types::CompletionItemKind;

fn conv(self) -> <Self as Conv>::Output {
fn conv(self) -> Self::Output {
use return_types::CompletionItemKind::*;
match self {
CompletionItemKind::Keyword => Keyword,
Expand All @@ -74,6 +75,17 @@ impl Conv for CompletionItemKind {
}
}

impl Conv for Severity {
type Output = return_types::MarkerSeverity;

fn conv(self) -> Self::Output {
match self {
Severity::Error => return_types::MarkerSeverity::Error,
Severity::WeakWarning => return_types::MarkerSeverity::Hint,
}
}
}

impl ConvWith<&LineIndex> for &AtomTextEdit {
type Output = return_types::TextEdit;

Expand Down Expand Up @@ -124,11 +136,81 @@ impl ConvWith<&LineIndex> for CompletionItem {
return_types::CompletionItemInsertTextRule::InsertAsSnippet
}
},
documentation: self
.documentation()
.map(|doc| return_types::MarkdownString { value: doc.as_str().to_string() }),
documentation: self.documentation().map(|doc| doc.conv()),
filterText: self.lookup().to_string(),
additionalTextEdits: additional_text_edits,
}
}
}

impl Conv for Documentation {
type Output = return_types::MarkdownString;
fn conv(self) -> Self::Output {
fn code_line_ignored_by_rustdoc(line: &str) -> bool {
let trimmed = line.trim();
trimmed == "#" || trimmed.starts_with("# ") || trimmed.starts_with("#\t")
}

let mut processed_lines = Vec::new();
let mut in_code_block = false;
for line in self.as_str().lines() {
if in_code_block && code_line_ignored_by_rustdoc(line) {
continue;
}

if line.starts_with("```") {
in_code_block ^= true
}

let line = if in_code_block && line.starts_with("```") && !line.contains("rust") {
"```rust"
} else {
line
};

processed_lines.push(line);
}

return_types::MarkdownString { value: processed_lines.join("\n") }
}
}

impl Conv for FunctionSignature {
type Output = return_types::SignatureInformation;
fn conv(self) -> Self::Output {
use return_types::{ParameterInformation, SignatureInformation};

let label = self.to_string();
let documentation = self.doc.map(|it| it.conv());

let parameters: Vec<ParameterInformation> = self
.parameters
.into_iter()
.map(|param| ParameterInformation { label: param })
.collect();

SignatureInformation { label, documentation, parameters }
}
}

impl ConvWith<&LineIndex> for RangeInfo<Vec<NavigationTarget>> {
type Output = Vec<return_types::LocationLink>;
fn conv_with(self, line_index: &LineIndex) -> Self::Output {
let selection = self.range.conv_with(&line_index);
self.info
.into_iter()
.map(|nav| {
let range = nav.full_range().conv_with(&line_index);

let target_selection_range =
nav.focus_range().map(|it| it.conv_with(&line_index)).unwrap_or(range);

return_types::LocationLink {
originSelectionRange: selection,
range,
targetSelectionRange: target_selection_range,
}
})
.collect()
}
}
60 changes: 51 additions & 9 deletions wasm-demo/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![cfg(target_arch = "wasm32")]
#![allow(non_snake_case)]

use ra_ide_api::{Analysis, FileId, FilePosition, Severity};
use ra_ide_api::{Analysis, FileId, FilePosition};
use ra_syntax::SyntaxKind;
use wasm_bindgen::prelude::*;

Expand Down Expand Up @@ -57,10 +57,7 @@ impl WorldState {
d.range.conv_with(&line_index);
Diagnostic {
message: d.message,
severity: match d.severity {
Severity::Error => 8, // monaco MarkerSeverity.Error
Severity::WeakWarning => 1, // monaco MarkerSeverity.Hint
},
severity: d.severity.conv(),
startLineNumber,
startColumn,
endLineNumber,
Expand Down Expand Up @@ -199,12 +196,57 @@ impl WorldState {
.source_file_edits
.iter()
.flat_map(|sfe| sfe.edit.as_atoms())
.map(|atom| TextEdit {
range: atom.delete.conv_with(&line_index),
text: atom.insert.clone(),
})
.map(|atom| atom.conv_with(&line_index))
.collect();

serde_wasm_bindgen::to_value(&result).unwrap()
}

pub fn signature_help(&self, line_number: u32, column: u32) -> JsValue {
log::warn!("signature_help");
let line_index = self.analysis.file_line_index(self.file_id).unwrap();

let pos = Position { line_number, column }.conv_with((&line_index, self.file_id));
let call_info = match self.analysis.call_info(pos) {
Ok(Some(call_info)) => call_info,
_ => return JsValue::NULL,
};

let sig_info = call_info.signature.conv();

let result = SignatureHelp {
signatures: [sig_info],
activeSignature: 0,
activeParameter: call_info.active_parameter,
};
serde_wasm_bindgen::to_value(&result).unwrap()
}

pub fn definition(&self, line_number: u32, column: u32) -> JsValue {
log::warn!("definition");
let line_index = self.analysis.file_line_index(self.file_id).unwrap();

let pos = Position { line_number, column }.conv_with((&line_index, self.file_id));
let nav_info = match self.analysis.goto_definition(pos) {
Ok(Some(nav_info)) => nav_info,
_ => return JsValue::NULL,
};

let res = nav_info.conv_with(&line_index);
serde_wasm_bindgen::to_value(&res).unwrap()
}

pub fn type_definition(&self, line_number: u32, column: u32) -> JsValue {
log::warn!("type_definition");
let line_index = self.analysis.file_line_index(self.file_id).unwrap();

let pos = Position { line_number, column }.conv_with((&line_index, self.file_id));
let nav_info = match self.analysis.goto_type_definition(pos) {
Ok(Some(nav_info)) => nav_info,
_ => return JsValue::NULL,
};

let res = nav_info.conv_with(&line_index);
serde_wasm_bindgen::to_value(&res).unwrap()
}
}
38 changes: 37 additions & 1 deletion wasm-demo/src/return_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,17 @@ pub struct Diagnostic {
pub startColumn: u32,
pub endLineNumber: u32,
pub endColumn: u32,
pub severity: u32,
pub severity: MarkerSeverity,
}

#[allow(dead_code)]
#[derive(Serialize_repr)]
#[repr(u8)]
pub enum MarkerSeverity {
Hint = 1,
Info = 2,
Warning = 4,
Error = 8,
}

#[derive(Serialize)]
Expand Down Expand Up @@ -127,3 +137,29 @@ pub enum CompletionItemInsertTextRule {
*/
InsertAsSnippet = 4,
}

#[derive(Serialize)]
pub struct ParameterInformation {
pub label: String,
}

#[derive(Serialize)]
pub struct SignatureInformation {
pub label: String,
pub documentation: Option<MarkdownString>,
pub parameters: Vec<ParameterInformation>,
}

#[derive(Serialize)]
pub struct SignatureHelp {
pub signatures: [SignatureInformation; 1],
pub activeSignature: u32,
pub activeParameter: Option<usize>,
}

#[derive(Serialize)]
pub struct LocationLink {
pub originSelectionRange: Range,
pub range: Range,
pub targetSelectionRange: Range,
}
29 changes: 24 additions & 5 deletions wasm-demo/www/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ import encoding from 'text-encoding';

if (typeof TextEncoder === "undefined") {
// Edge polyfill, https://rustwasm.github.io/docs/wasm-bindgen/reference/browser-support.html
self.TextEncoder = encoding.TextEncoder
self.TextDecoder = encoding.TextDecoder
self.TextEncoder = encoding.TextEncoder;
self.TextDecoder = encoding.TextDecoder;
}

import './index.css';
Expand Down Expand Up @@ -118,7 +118,7 @@ monaco.languages.onLanguage(modeId, async () => {
position,
references,
],
}
},
};
});

Expand Down Expand Up @@ -147,10 +147,29 @@ monaco.languages.onLanguage(modeId, async () => {
monaco.languages.registerCompletionItemProvider(modeId, {
triggerCharacters: [".", ":", "="],
provideCompletionItems(m, pos) {
const suggestions = state.completions(pos.lineNumber, pos.column)
return { suggestions }
const suggestions = state.completions(pos.lineNumber, pos.column);
return { suggestions };
},
});
monaco.languages.registerSignatureHelpProvider(modeId, {
signatureHelpTriggerCharacters: ['(', ','],
provideSignatureHelp(m, pos) {
const value = state.signature_help(pos.lineNumber, pos.column);
if (!value) return null;
return {
value,
dispose() { },
};
},
});
monaco.languages.registerDefinitionProvider(modeId, {
provideDefinition: (m, pos) => state.definition(pos.lineNumber, pos.column)
.map(def => ({ ...def, uri: m.uri })),
});
monaco.languages.registerTypeDefinitionProvider(modeId, {
provideTypeDefinition: (m, pos) => state.type_definition(pos.lineNumber, pos.column)
.map(def => ({ ...def, uri: m.uri })),
});

class TokenState {
constructor(line = 0) {
Expand Down