Skip to content

Commit

Permalink
[move-analyzer] Add Docstring rendering on-hover (move-language#328)
Browse files Browse the repository at this point in the history
* [move-analyzer] Add docstring rendering for consts, structs, functions

* [move-analyzer] Optimize docstring construction

* [move-analyzer] Add rendering for docstrings across other modules

* [move-analyzer] Fix M1.move tests

* [move-analyzer] Add unit tests for docstring construction

* [move-analyzer] Add integration tests for docstring construction

* [move-analyzer] Add support for /** .. */ docstring comments

* [move-analyzer] Update unit/integration tests to test asterix-based docstrings

* [move-analyzer] Fix general PR comments

* [move-analyzer] Improve extract_doc_string readability

* [move-analyzer] Fix linter issues
  • Loading branch information
Deagler authored Aug 6, 2022
1 parent 9169307 commit 3c47a95
Show file tree
Hide file tree
Showing 10 changed files with 570 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
**/target
**/*.rs.bk
.idea/
**/.vscode

# Ignore wallet mnemonic files used for deterministic key derivation
*.mnemonic
Expand Down
2 changes: 1 addition & 1 deletion language/move-analyzer/editors/code/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
"max-len": [
"warn",
{
"code": 100,
"code": 120,
"ignoreUrls": true
}
],
Expand Down
22 changes: 20 additions & 2 deletions language/move-analyzer/editors/code/src/commands/lsp_command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {
SymbolInformation,
DocumentSymbol,
} from 'vscode-languageclient';
import { DocumentSymbolRequest } from 'vscode-languageclient';
import { DocumentSymbolRequest, HoverRequest } from 'vscode-languageclient';
import type { Context } from '../context';

/**
Expand All @@ -12,7 +12,7 @@ import type { Context } from '../context';
export async function textDocumentDocumentSymbol(
context: Readonly<Context>,
params: DocumentSymbolParams,
)
)
: Promise<SymbolInformation[] | DocumentSymbol[] | null> {
const client = context.getClient();
if (client === undefined) {
Expand All @@ -22,3 +22,21 @@ export async function textDocumentDocumentSymbol(
// Send the request to the language client.
return client.sendRequest(DocumentSymbolRequest.type, params);
}


/**
* An LSP command textDocument/hover
*/
export async function textDocumentHover(
context: Readonly<Context>,
params: DocumentSymbolParams,
)
: Promise<SymbolInformation[] | DocumentSymbol[] | null> {
const client = context.getClient();
if (client === undefined) {
return Promise.reject(new Error('No language client connected.'));
}

// Send the request to the language client.
return client.sendRequest(HoverRequest.method, params);
}
1 change: 1 addition & 0 deletions language/move-analyzer/editors/code/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,5 @@ export async function activate(extensionContext: Readonly<vscode.ExtensionContex
// All other utilities provided by this extension occur via the language server.
await context.startClient();
context.registerCommand('textDocumentDocumentSymbol', commands.textDocumentDocumentSymbol);
context.registerCommand('textDocumentHover', commands.textDocumentHover);
}
22 changes: 22 additions & 0 deletions language/move-analyzer/editors/code/tests/lsp-demo/sources/M2.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module Symbols::M2 {

/// Constant containing the answer to the universe
const DOCUMENTED_CONSTANT: u64 = 42;

/**
This is a multiline docstring
This docstring has empty lines.
It uses the ** format instead of ///
*/
fun other_doc_struct(): Symbols::M3::OtherDocStruct {
Symbols::M3::create_other_struct(DOCUMENTED_CONSTANT)
}

use Symbols::M3::{Self, OtherDocStruct};

fun other_doc_struct_import(): OtherDocStruct {
M3::create_other_struct(7)
}
}
12 changes: 12 additions & 0 deletions language/move-analyzer/editors/code/tests/lsp-demo/sources/M3.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Symbols::M3 {

/// Documented struct in another module
struct OtherDocStruct has drop {
some_field: u64,
}

/// Documented initializer in another module
public fun create_other_struct(v: u64): OtherDocStruct {
OtherDocStruct { some_field: v }
}
}
79 changes: 79 additions & 0 deletions language/move-analyzer/editors/code/tests/lsp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as Mocha from 'mocha';
import * as path from 'path';
import * as vscode from 'vscode';
import * as lc from 'vscode-languageclient';
import type { MarkupContent } from 'vscode-languageclient';

Mocha.suite('LSP', () => {
Mocha.test('textDocument/documentSymbol', async () => {
Expand Down Expand Up @@ -49,4 +50,82 @@ Mocha.suite('LSP', () => {
assert.deepStrictEqual(syms[0]?.children[3].name, 'this_is_a_test');
assert.deepStrictEqual(syms[0]?.children[3]?.detail, '["test", "expected_failure"]');
});

Mocha.test('textDocument/hover for definition in the same module', async () => {
const ext = vscode.extensions.getExtension('move.move-analyzer');
assert.ok(ext);

await ext.activate(); // Synchronous waiting for activation to complete

// 1. get workdir
const workDir = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? '';

// 2. open doc
const docs = await vscode.workspace.openTextDocument(
path.join(workDir, 'sources/M2.move'),
);
await vscode.window.showTextDocument(docs);

// 3. execute command
const params: lc.HoverParams = {
textDocument: {
uri: docs.uri.toString(),
},
position: {
line: 12,
character: 8,
},
};

const hoverResult: lc.Hover | undefined =
await vscode.commands.executeCommand(
'move-analyzer.textDocumentHover',
params,
);

assert.ok(hoverResult);
assert.deepStrictEqual((hoverResult.contents as MarkupContent).value,
// eslint-disable-next-line max-len
'fun Symbols::M2::other_doc_struct(): Symbols::M3::OtherDocStruct\n\n\nThis is a multiline docstring\n\nThis docstring has empty lines.\n\nIt uses the ** format instead of ///\n\n');

});

Mocha.test('textDocument/hover for definition in an external module', async () => {
const ext = vscode.extensions.getExtension('move.move-analyzer');
assert.ok(ext);

await ext.activate(); // Synchronous waiting for activation to complete

// 1. get workdir
const workDir = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? '';

// 2. open doc
const docs = await vscode.workspace.openTextDocument(
path.join(workDir, 'sources/M2.move'),
);
await vscode.window.showTextDocument(docs);

// 3. execute command
const params: lc.HoverParams = {
textDocument: {
uri: docs.uri.toString(),
},
position: {
line: 18,
character: 35,
},
};

const hoverResult: lc.Hover | undefined =
await vscode.commands.executeCommand(
'move-analyzer.textDocumentHover',
params,
);


assert.ok(hoverResult);
assert.deepStrictEqual((hoverResult.contents as MarkupContent).value,
'Symbols::M3::OtherDocStruct\n\nDocumented struct in another module\n');

});
});
Loading

0 comments on commit 3c47a95

Please sign in to comment.