-
Notifications
You must be signed in to change notification settings - Fork 54
wasm demo completions support #2
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
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
2f18550
rudimentary completions support
JasperDeSutter 7b833dd
add initial conv module
JasperDeSutter 5cfaf7c
use enums with serde_repr instead of u32
JasperDeSutter 5661303
Merge remote-tracking branch 'origin/src' into completions
JasperDeSutter 9f3e561
use conv_with instead of file_pos and range
JasperDeSutter 7d8ed7b
additionalTextEdits handling
JasperDeSutter File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
reorder_modules = false | ||
use_small_heuristics = "Max" | ||
newline_style = "Unix" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
use super::return_types; | ||
use ra_ide_api::{ | ||
CompletionItem, CompletionItemKind, FileId, FilePosition, InsertTextFormat, LineCol, LineIndex, | ||
}; | ||
use ra_syntax::TextRange; | ||
use ra_text_edit::AtomTextEdit; | ||
|
||
pub trait Conv { | ||
type Output; | ||
fn conv(self) -> Self::Output; | ||
} | ||
|
||
pub trait ConvWith<CTX> { | ||
type Output; | ||
fn conv_with(self, ctx: CTX) -> Self::Output; | ||
} | ||
|
||
#[derive(Clone, Copy)] | ||
pub struct Position { | ||
pub line_number: u32, | ||
pub column: u32, | ||
} | ||
|
||
impl ConvWith<(&LineIndex, FileId)> for Position { | ||
type Output = FilePosition; | ||
|
||
fn conv_with(self, (line_index, file_id): (&LineIndex, FileId)) -> Self::Output { | ||
let line_col = LineCol { line: self.line_number - 1, col_utf16: self.column - 1 }; | ||
let offset = line_index.offset(line_col); | ||
FilePosition { file_id, offset } | ||
} | ||
} | ||
|
||
impl ConvWith<&LineIndex> for TextRange { | ||
type Output = return_types::Range; | ||
|
||
fn conv_with(self, line_index: &LineIndex) -> Self::Output { | ||
let start = line_index.line_col(self.start()); | ||
let end = line_index.line_col(self.end()); | ||
|
||
return_types::Range { | ||
startLineNumber: start.line + 1, | ||
startColumn: start.col_utf16 + 1, | ||
endLineNumber: end.line + 1, | ||
endColumn: end.col_utf16 + 1, | ||
} | ||
} | ||
} | ||
|
||
impl Conv for CompletionItemKind { | ||
type Output = return_types::CompletionItemKind; | ||
|
||
fn conv(self) -> <Self as Conv>::Output { | ||
use return_types::CompletionItemKind::*; | ||
match self { | ||
CompletionItemKind::Keyword => Keyword, | ||
CompletionItemKind::Snippet => Snippet, | ||
CompletionItemKind::Module => Module, | ||
CompletionItemKind::Function => Function, | ||
CompletionItemKind::Struct => Struct, | ||
CompletionItemKind::Enum => Enum, | ||
CompletionItemKind::EnumVariant => EnumMember, | ||
CompletionItemKind::BuiltinType => Struct, | ||
CompletionItemKind::Binding => Variable, | ||
CompletionItemKind::Field => Field, | ||
CompletionItemKind::Trait => Interface, | ||
CompletionItemKind::TypeAlias => Struct, | ||
CompletionItemKind::Const => Constant, | ||
CompletionItemKind::Static => Value, | ||
CompletionItemKind::Method => Method, | ||
CompletionItemKind::TypeParam => TypeParameter, | ||
CompletionItemKind::Macro => Method, | ||
} | ||
} | ||
} | ||
|
||
impl ConvWith<&LineIndex> for &AtomTextEdit { | ||
type Output = return_types::TextEdit; | ||
|
||
fn conv_with(self, line_index: &LineIndex) -> Self::Output { | ||
let text = self.insert.clone(); | ||
return_types::TextEdit { range: self.delete.conv_with(line_index), text } | ||
} | ||
} | ||
|
||
impl ConvWith<&LineIndex> for CompletionItem { | ||
type Output = return_types::CompletionItem; | ||
|
||
fn conv_with(self, line_index: &LineIndex) -> Self::Output { | ||
let mut additional_text_edits = Vec::new(); | ||
let mut text_edit = None; | ||
// LSP does not allow arbitrary edits in completion, so we have to do a | ||
// non-trivial mapping here. | ||
for atom_edit in self.text_edit().as_atoms() { | ||
if self.source_range().is_subrange(&atom_edit.delete) { | ||
text_edit = Some(if atom_edit.delete == self.source_range() { | ||
atom_edit.conv_with(line_index) | ||
} else { | ||
assert!(self.source_range().end() == atom_edit.delete.end()); | ||
let range1 = | ||
TextRange::from_to(atom_edit.delete.start(), self.source_range().start()); | ||
let range2 = self.source_range(); | ||
let edit1 = AtomTextEdit::replace(range1, String::new()); | ||
let edit2 = AtomTextEdit::replace(range2, atom_edit.insert.clone()); | ||
additional_text_edits.push(edit1.conv_with(line_index)); | ||
edit2.conv_with(line_index) | ||
}) | ||
} else { | ||
assert!(self.source_range().intersection(&atom_edit.delete).is_none()); | ||
additional_text_edits.push(atom_edit.conv_with(line_index)); | ||
} | ||
} | ||
let return_types::TextEdit { range, text } = text_edit.unwrap(); | ||
|
||
return_types::CompletionItem { | ||
kind: self.kind().unwrap_or(CompletionItemKind::Struct).conv(), | ||
label: self.label().to_string(), | ||
range, | ||
detail: self.detail().map(|it| it.to_string()), | ||
insertText: text, | ||
insertTextRules: match self.insert_text_format() { | ||
InsertTextFormat::PlainText => return_types::CompletionItemInsertTextRule::None, | ||
InsertTextFormat::Snippet => { | ||
return_types::CompletionItemInsertTextRule::InsertAsSnippet | ||
} | ||
}, | ||
documentation: self | ||
.documentation() | ||
.map(|doc| return_types::MarkdownString { value: doc.as_str().to_string() }), | ||
filterText: self.lookup().to_string(), | ||
additionalTextEdits: additional_text_edits, | ||
} | ||
} | ||
} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels bad that we need to literally duplicate this between ra_lsp_server and wasm demo, but still, I think its the right thing to do. Wrapping rust-analyzer into some front-end is a ton of boilerplate (b/c the API surface is large), but it is still much easier than implementing the "compiler" itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There might be some opportunity for reducing the code duplication, but that would probably require having an entire "lsp-types"-like crate for monaco.
This way rust-analyzer could have an intermediate crate mapping ra-ide to lsp, which both lsp-server and the wasm demo could use.
It sounds like too much effort to me, including the fact that monaco itself isn't stable and changes API regularly and does everything just a little differently.