mirror of
https://github.com/fluencelabs/aqua-vscode
synced 2025-04-25 00:22:15 +00:00
feat(server): Support show types on hover [LNG-285] (#64)
This commit is contained in:
parent
fdb17c9266
commit
41fd59fe31
6
package-lock.json
generated
6
package-lock.json
generated
@ -28,6 +28,12 @@
|
||||
"vscode": "^1.50.0"
|
||||
}
|
||||
},
|
||||
"../aqua/language-server/language-server-npm": {
|
||||
"name": "@fluencelabs/aqua-language-server-api",
|
||||
"version": "0.13.0",
|
||||
"extraneous": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@eslint/eslintrc": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
|
||||
|
14
server/package-lock.json
generated
14
server/package-lock.json
generated
@ -8,7 +8,7 @@
|
||||
"name": "aqua-ls-server",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@fluencelabs/aqua-language-server-api": "0.13.0",
|
||||
"@fluencelabs/aqua-language-server-api": "0.13.1",
|
||||
"global-dirs": "^3.0.0",
|
||||
"vscode-languageserver": "^7.0.0",
|
||||
"vscode-languageserver-textdocument": "^1.0.4"
|
||||
@ -30,9 +30,9 @@
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@fluencelabs/aqua-language-server-api": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.13.0.tgz",
|
||||
"integrity": "sha512-NWrKnDAwc7GjIFbo1ph1AdydakIkvJC19Euh+1NnLMBZVgpSJ1nP28ZhzlbvMeYiwrJ2P/ZKy8ZahmsvUl4IaQ=="
|
||||
"version": "0.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.13.1.tgz",
|
||||
"integrity": "sha512-RipKk2NZiwX72eEN5gfDbdzljsGGMva01sCukrdrxV+zdyh+9TVZCjlpaVwZsjW/5e1wRCk0DE+RbVTlDc3Ktg=="
|
||||
},
|
||||
"node_modules/global-dirs": {
|
||||
"version": "3.0.0",
|
||||
@ -97,9 +97,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fluencelabs/aqua-language-server-api": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.13.0.tgz",
|
||||
"integrity": "sha512-NWrKnDAwc7GjIFbo1ph1AdydakIkvJC19Euh+1NnLMBZVgpSJ1nP28ZhzlbvMeYiwrJ2P/ZKy8ZahmsvUl4IaQ=="
|
||||
"version": "0.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.13.1.tgz",
|
||||
"integrity": "sha512-RipKk2NZiwX72eEN5gfDbdzljsGGMva01sCukrdrxV+zdyh+9TVZCjlpaVwZsjW/5e1wRCk0DE+RbVTlDc3Ktg=="
|
||||
},
|
||||
"global-dirs": {
|
||||
"version": "3.0.0",
|
||||
|
@ -11,12 +11,12 @@
|
||||
"url": "https://github.com/fluencelabs/aqua"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fluencelabs/aqua-language-server-api": "0.13.0",
|
||||
"@fluencelabs/aqua-language-server-api": "0.13.1",
|
||||
"global-dirs": "^3.0.0",
|
||||
"vscode-languageserver": "^7.0.0",
|
||||
"vscode-languageserver-textdocument": "^1.0.4"
|
||||
},
|
||||
"scripts": {
|
||||
"get-root": "npm root --globall"
|
||||
"get-root": "npm root --global"
|
||||
}
|
||||
}
|
||||
|
49
server/src/search.ts
Normal file
49
server/src/search.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import type { TokenInfo, TokenLink, TokenLocation } from '@fluencelabs/aqua-language-server-api/aqua-lsp-api';
|
||||
import type { Position } from 'vscode-languageserver-textdocument';
|
||||
|
||||
function isToken(location: TokenLocation, position: Position, name: string) {
|
||||
return (
|
||||
location.name == name &&
|
||||
location.startLine <= position.line &&
|
||||
location.startCol <= position.character &&
|
||||
location.endLine >= position.line &&
|
||||
location.endCol >= position.character
|
||||
);
|
||||
}
|
||||
|
||||
function isTokenByLocation(location: TokenLocation, locationRight: TokenLocation) {
|
||||
return (
|
||||
location.startLine <= locationRight.startLine &&
|
||||
location.startCol <= locationRight.startCol &&
|
||||
location.endLine >= locationRight.endLine &&
|
||||
location.endCol >= locationRight.endCol
|
||||
);
|
||||
}
|
||||
|
||||
export function searchDefinition(position: Position, name: string, locations: TokenLink[]): TokenLink | undefined {
|
||||
return locations.find((token) => isToken(token.current, position, name));
|
||||
}
|
||||
|
||||
// find a token by position in the definition.
|
||||
// If there is no token, look for the definition token in the locations,
|
||||
// and then look up the token information from the token found.
|
||||
export function searchInfo(
|
||||
position: Position,
|
||||
name: string,
|
||||
tokens: TokenInfo[],
|
||||
locations: TokenLink[],
|
||||
): TokenInfo | undefined {
|
||||
const tokenInfo = tokens.find((token) => isToken(token.location, position, name));
|
||||
|
||||
if (tokenInfo) {
|
||||
return tokenInfo;
|
||||
}
|
||||
|
||||
const tokenLink = searchDefinition(position, name, locations);
|
||||
|
||||
if (tokenLink) {
|
||||
return tokens.find((token) => isTokenByLocation(token.location, tokenLink.definition));
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
@ -9,14 +9,15 @@ import {
|
||||
TextDocumentSyncKind,
|
||||
} from 'vscode-languageserver/node';
|
||||
import type { WorkspaceFolder } from 'vscode-languageserver-protocol';
|
||||
import { Position, TextDocument } from 'vscode-languageserver-textdocument';
|
||||
import type { DefinitionParams, Location } from 'vscode-languageserver';
|
||||
|
||||
import type { TokenLink } from '@fluencelabs/aqua-language-server-api/aqua-lsp-api';
|
||||
import { TextDocument } from 'vscode-languageserver-textdocument';
|
||||
import type { DefinitionParams, Hover, HoverParams, Location, MarkupContent } from 'vscode-languageserver';
|
||||
import { MarkupKind } from 'vscode-languageserver';
|
||||
import type { TokenInfo, TokenLink } from '@fluencelabs/aqua-language-server-api/aqua-lsp-api';
|
||||
|
||||
import { compileAqua } from './validation';
|
||||
import { FluenceCli } from './cli';
|
||||
import { Settings, SettingsManager } from './settings';
|
||||
import { searchDefinition, searchInfo } from './search';
|
||||
|
||||
// Create a connection to the server, using Node's IPC as a transport.
|
||||
// Also include all preview / proposed LSP features.
|
||||
@ -37,37 +38,52 @@ function createSettingsManager(cliPath?: string, defaultSettings?: Settings): Se
|
||||
|
||||
let documentSettings = createSettingsManager();
|
||||
|
||||
function searchDefinition(position: Position, name: string, locations: TokenLink[]): TokenLink | undefined {
|
||||
return locations.find(
|
||||
(token) =>
|
||||
token.current.name == name &&
|
||||
token.current.startLine <= position.line &&
|
||||
token.current.startCol <= position.character &&
|
||||
token.current.endLine >= position.line &&
|
||||
token.current.endCol >= position.character,
|
||||
);
|
||||
interface PageInfo {
|
||||
links: TokenLink[];
|
||||
tokens: TokenInfo[];
|
||||
}
|
||||
|
||||
// Cache all locations of all open documents
|
||||
const allLocations: Map<string, TokenLink[]> = new Map();
|
||||
const allPageInfo: Map<string, PageInfo> = new Map();
|
||||
|
||||
function onHover({ textDocument, position }: HoverParams): Hover | null {
|
||||
const doc = documents.get(textDocument.uri);
|
||||
const currentPage = allPageInfo.get(textDocument.uri);
|
||||
|
||||
if (doc == undefined || currentPage == undefined) {
|
||||
throw new Error(`Cannot find compilation info about page: ${textDocument.uri}`);
|
||||
}
|
||||
|
||||
const token = searchInfo(position, doc.uri.replace('file://', ''), currentPage.tokens, currentPage.links);
|
||||
if (token) {
|
||||
const content: MarkupContent = { kind: MarkupKind.PlainText, value: token.type };
|
||||
|
||||
const hover: Hover = { contents: content };
|
||||
|
||||
return hover;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
connection.onHover(onHover);
|
||||
|
||||
async function onDefinition({ textDocument, position }: DefinitionParams): Promise<Location[]> {
|
||||
connection.console.log('onDefinition event');
|
||||
const doc = documents.get(textDocument.uri);
|
||||
const currentLocations = allLocations.get(textDocument.uri);
|
||||
const currentPage = allPageInfo.get(textDocument.uri);
|
||||
|
||||
if (doc == undefined || currentLocations == undefined) {
|
||||
if (doc == undefined || currentPage == undefined) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const token = searchDefinition(position, doc.uri.replace('file://', ''), currentLocations);
|
||||
connection.console.log('found token: ' + JSON.stringify(token));
|
||||
const tokenLink = searchDefinition(position, doc.uri.replace('file://', ''), currentPage.links);
|
||||
|
||||
if (token == undefined) {
|
||||
if (tokenLink == undefined) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const definition = token.definition;
|
||||
const definition = tokenLink.definition;
|
||||
|
||||
return [
|
||||
{
|
||||
@ -117,6 +133,7 @@ connection.onInitialize((params: InitializeParams) => {
|
||||
capabilities: {
|
||||
textDocumentSync: TextDocumentSyncKind.Full,
|
||||
definitionProvider: true,
|
||||
hoverProvider: true,
|
||||
},
|
||||
};
|
||||
|
||||
@ -163,9 +180,9 @@ async function validateDocument(textDocument: TextDocument): Promise<void> {
|
||||
|
||||
connection.console.log(`validateDocument ${textDocument.uri} with settings ${JSON.stringify(settings)}`);
|
||||
|
||||
const [diagnostics, locations] = await compileAqua(settings, textDocument, folders, connection.console);
|
||||
const [diagnostics, locations, tokenInfos] = await compileAqua(settings, textDocument, folders, connection.console);
|
||||
|
||||
allLocations.set(textDocument.uri, locations);
|
||||
allPageInfo.set(textDocument.uri, { links: locations, tokens: tokenInfos });
|
||||
|
||||
// Send the computed diagnostics to VSCode.
|
||||
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
|
||||
|
@ -5,7 +5,13 @@ import type { TextDocument } from 'vscode-languageserver-textdocument';
|
||||
import { Diagnostic, DiagnosticSeverity, RemoteConsole } from 'vscode-languageserver/node';
|
||||
import type { WorkspaceFolder } from 'vscode-languageserver-protocol';
|
||||
|
||||
import { AquaLSP, ErrorInfo, TokenLink, WarningInfo } from '@fluencelabs/aqua-language-server-api/aqua-lsp-api';
|
||||
import {
|
||||
AquaLSP,
|
||||
ErrorInfo,
|
||||
TokenInfo,
|
||||
TokenLink,
|
||||
WarningInfo,
|
||||
} from '@fluencelabs/aqua-language-server-api/aqua-lsp-api';
|
||||
|
||||
import type { Settings } from './settings';
|
||||
|
||||
@ -141,7 +147,7 @@ export async function compileAqua(
|
||||
textDocument: TextDocument,
|
||||
folders: WorkspaceFolder[],
|
||||
console: RemoteConsole,
|
||||
): Promise<[Diagnostic[], TokenLink[]]> {
|
||||
): Promise<[Diagnostic[], TokenLink[], TokenInfo[]]> {
|
||||
const uri = textDocument.uri.replace('file://', '');
|
||||
|
||||
const imports = getImports(settings, textDocument, folders, console);
|
||||
@ -184,5 +190,5 @@ export async function compileAqua(
|
||||
|
||||
const locations = result.locations.concat(links);
|
||||
|
||||
return [diagnostics, locations];
|
||||
return [diagnostics, locations, result.tokens];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user