Skip to content

Commit

Permalink
feat: goto definition (#49)
Browse files Browse the repository at this point in the history
Clean up comments

Replace use of get_word_from_file_params() in get_goto_def_resp()

Use lsp_pos_of_point()

Refactor get word logic into function
  • Loading branch information
WillLillis authored Dec 22, 2023
1 parent 7b7298d commit 77503f5
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 4 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

## Goal

Provide hovering, autocompletion, and signature help for assembly files written
in the GAS/NASM or GO assembly flavors. It supports assembly files for the x86
or x86_64 instruction sets.
Provide hovering, autocompletion, signature help, and go to definition for assembly files
written in the GAS/NASM or GO assembly flavors. It supports assembly files for
the x86 or x86_64 instruction sets.

This tool can serve as reference when reading the assembly output of a program.
This way you can query what each command exactly does and deliberate about
Expand Down Expand Up @@ -67,6 +67,10 @@ x86_64 = true

![](https://github.com/bergercookie/asm-lsp/blob/master/demo/autocomplete.gif)

### Goto Definition

![](https://github.com/bergercookie/asm-lsp/blob/master/demo/gotodef.gif)

### Signature Help

![](https://github.com/bergercookie/asm-lsp/blob/master/demo/signaturehelp.gif)
Expand Down
Binary file added demo/gotodef.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 30 additions & 1 deletion src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use asm_lsp::*;

use log::{error, info};
use lsp_types::notification::{DidChangeTextDocument, DidOpenTextDocument};
use lsp_types::request::{Completion, DocumentSymbolRequest, HoverRequest, SignatureHelpRequest};
use lsp_types::request::{
Completion, DocumentSymbolRequest, GotoDefinition, HoverRequest, SignatureHelpRequest,
};
use lsp_types::*;

use crate::lsp::{get_document_symbols, get_target_config, instr_filter_targets};
Expand Down Expand Up @@ -38,6 +40,8 @@ pub fn main() -> anyhow::Result<()> {
..Default::default()
});

let definition_provider = Some(OneOf::Left(true));

let text_document_sync = Some(TextDocumentSyncCapability::Kind(
TextDocumentSyncKind::INCREMENTAL,
));
Expand All @@ -55,6 +59,7 @@ pub fn main() -> anyhow::Result<()> {
hover_provider,
completion_provider,
signature_help_provider,
definition_provider,
text_document_sync,
document_symbol_provider: Some(OneOf::Left(true)),
..ServerCapabilities::default()
Expand Down Expand Up @@ -264,6 +269,30 @@ fn main_loop(
// don't know what to suggest
connection.sender.send(Message::Response(res.clone()))?;
}
} else if let Ok((id, params)) = cast_req::<GotoDefinition>(req.clone()) {
let res = Response {
id: id.clone(),
result: None,
error: None,
};
if let Some(ref doc) = curr_doc {
let def_res = get_goto_def_resp(doc, &mut parser, &mut tree, &params);
match def_res {
Some(_) => {
let result = serde_json::to_value(&def_res).unwrap();
let result = Response {
id: id.clone(),
result: Some(result),
error: None,
};
connection.sender.send(Message::Response(result))?;
}
None => {
// don't know what to suggest
connection.sender.send(Message::Response(res.clone()))?;
}
}
}
} else if let Ok((id, params)) = cast_req::<DocumentSymbolRequest>(req.clone()) {
// DocumentSymbolRequest ---------------------------------------------------------------
let res = Response {
Expand Down
72 changes: 72 additions & 0 deletions src/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,27 @@ pub fn get_word_from_file_params(
}
}

/// Returns a string slice to the word in doc specified by the position params
pub fn get_word_from_pos_params<'a>(
doc: &'a FullTextDocument,
pos_params: &TextDocumentPositionParams,
) -> &'a str {
let line_contents = doc.get_content(Some(Range {
start: Position {
line: pos_params.position.line,
character: 0,
},
end: Position {
line: pos_params.position.line,
character: u32::MAX,
},
}));

let (word_start, word_end) =
find_word_at_pos(line_contents, pos_params.position.character as usize);
&line_contents[word_start..word_end]
}

/// Function allowing us to connect tree sitter's logging with the log crate
pub fn tree_sitter_logger(log_type: tree_sitter::LogType, message: &str) {
// map tree-sitter log types to log levels, for now set everything to Trace
Expand Down Expand Up @@ -668,6 +689,57 @@ pub fn get_sig_help_resp(
None
}

pub fn get_goto_def_resp(
curr_doc: &FullTextDocument,
parser: &mut Parser,
curr_tree: &mut Option<Tree>,
params: &GotoDefinitionParams,
) -> Option<GotoDefinitionResponse> {
let doc = curr_doc.get_content(None);
*curr_tree = parser.parse(doc, curr_tree.as_ref());

if let Some(tree) = curr_tree {
static QUERY_LABEL: Lazy<tree_sitter::Query> = Lazy::new(|| {
tree_sitter::Query::new(tree_sitter_asm::language(), "(label) @label").unwrap()
});

let is_not_ident_char = |c: char| !(c.is_alphanumeric() || c == '_');
let mut cursor = tree_sitter::QueryCursor::new();
let matches = cursor.matches(&QUERY_LABEL, tree.root_node(), doc.as_bytes());

let word = get_word_from_pos_params(curr_doc, &params.text_document_position_params);

for match_ in matches.into_iter() {
for cap in match_.captures.iter() {
let text = cap
.node
.utf8_text(doc.as_bytes())
.unwrap_or("")
.trim()
.trim_matches(is_not_ident_char);

if word.eq(text) {
let start = cap.node.start_position();
let end = cap.node.end_position();
return Some(GotoDefinitionResponse::Scalar(Location {
uri: params
.text_document_position_params
.text_document
.uri
.clone(),
range: Range {
start: lsp_pos_of_point(start),
end: lsp_pos_of_point(end),
},
}));
}
}
}
}

None
}

// Note: Some issues here regarding entangled lifetimes
// -- https://github.com/rust-lang/rust/issues/80389
// If issue is resolved, can add a separate lifetime "'b" to "word"
Expand Down

0 comments on commit 77503f5

Please sign in to comment.