mirror of
https://github.com/fluencelabs/aqua-vscode
synced 2025-04-25 08:32: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"
|
"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": {
|
"node_modules/@eslint/eslintrc": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
|
"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",
|
"name": "aqua-ls-server",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fluencelabs/aqua-language-server-api": "0.13.0",
|
"@fluencelabs/aqua-language-server-api": "0.13.1",
|
||||||
"global-dirs": "^3.0.0",
|
"global-dirs": "^3.0.0",
|
||||||
"vscode-languageserver": "^7.0.0",
|
"vscode-languageserver": "^7.0.0",
|
||||||
"vscode-languageserver-textdocument": "^1.0.4"
|
"vscode-languageserver-textdocument": "^1.0.4"
|
||||||
@ -30,9 +30,9 @@
|
|||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/@fluencelabs/aqua-language-server-api": {
|
"node_modules/@fluencelabs/aqua-language-server-api": {
|
||||||
"version": "0.13.0",
|
"version": "0.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.13.1.tgz",
|
||||||
"integrity": "sha512-NWrKnDAwc7GjIFbo1ph1AdydakIkvJC19Euh+1NnLMBZVgpSJ1nP28ZhzlbvMeYiwrJ2P/ZKy8ZahmsvUl4IaQ=="
|
"integrity": "sha512-RipKk2NZiwX72eEN5gfDbdzljsGGMva01sCukrdrxV+zdyh+9TVZCjlpaVwZsjW/5e1wRCk0DE+RbVTlDc3Ktg=="
|
||||||
},
|
},
|
||||||
"node_modules/global-dirs": {
|
"node_modules/global-dirs": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
@ -97,9 +97,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fluencelabs/aqua-language-server-api": {
|
"@fluencelabs/aqua-language-server-api": {
|
||||||
"version": "0.13.0",
|
"version": "0.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.13.1.tgz",
|
||||||
"integrity": "sha512-NWrKnDAwc7GjIFbo1ph1AdydakIkvJC19Euh+1NnLMBZVgpSJ1nP28ZhzlbvMeYiwrJ2P/ZKy8ZahmsvUl4IaQ=="
|
"integrity": "sha512-RipKk2NZiwX72eEN5gfDbdzljsGGMva01sCukrdrxV+zdyh+9TVZCjlpaVwZsjW/5e1wRCk0DE+RbVTlDc3Ktg=="
|
||||||
},
|
},
|
||||||
"global-dirs": {
|
"global-dirs": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
|
@ -11,12 +11,12 @@
|
|||||||
"url": "https://github.com/fluencelabs/aqua"
|
"url": "https://github.com/fluencelabs/aqua"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fluencelabs/aqua-language-server-api": "0.13.0",
|
"@fluencelabs/aqua-language-server-api": "0.13.1",
|
||||||
"global-dirs": "^3.0.0",
|
"global-dirs": "^3.0.0",
|
||||||
"vscode-languageserver": "^7.0.0",
|
"vscode-languageserver": "^7.0.0",
|
||||||
"vscode-languageserver-textdocument": "^1.0.4"
|
"vscode-languageserver-textdocument": "^1.0.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"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,
|
TextDocumentSyncKind,
|
||||||
} from 'vscode-languageserver/node';
|
} from 'vscode-languageserver/node';
|
||||||
import type { WorkspaceFolder } from 'vscode-languageserver-protocol';
|
import type { WorkspaceFolder } from 'vscode-languageserver-protocol';
|
||||||
import { Position, TextDocument } from 'vscode-languageserver-textdocument';
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
||||||
import type { DefinitionParams, Location } from 'vscode-languageserver';
|
import type { DefinitionParams, Hover, HoverParams, Location, MarkupContent } from 'vscode-languageserver';
|
||||||
|
import { MarkupKind } from 'vscode-languageserver';
|
||||||
import type { TokenLink } from '@fluencelabs/aqua-language-server-api/aqua-lsp-api';
|
import type { TokenInfo, TokenLink } from '@fluencelabs/aqua-language-server-api/aqua-lsp-api';
|
||||||
|
|
||||||
import { compileAqua } from './validation';
|
import { compileAqua } from './validation';
|
||||||
import { FluenceCli } from './cli';
|
import { FluenceCli } from './cli';
|
||||||
import { Settings, SettingsManager } from './settings';
|
import { Settings, SettingsManager } from './settings';
|
||||||
|
import { searchDefinition, searchInfo } from './search';
|
||||||
|
|
||||||
// Create a connection to the server, using Node's IPC as a transport.
|
// Create a connection to the server, using Node's IPC as a transport.
|
||||||
// Also include all preview / proposed LSP features.
|
// Also include all preview / proposed LSP features.
|
||||||
@ -37,37 +38,52 @@ function createSettingsManager(cliPath?: string, defaultSettings?: Settings): Se
|
|||||||
|
|
||||||
let documentSettings = createSettingsManager();
|
let documentSettings = createSettingsManager();
|
||||||
|
|
||||||
function searchDefinition(position: Position, name: string, locations: TokenLink[]): TokenLink | undefined {
|
interface PageInfo {
|
||||||
return locations.find(
|
links: TokenLink[];
|
||||||
(token) =>
|
tokens: TokenInfo[];
|
||||||
token.current.name == name &&
|
|
||||||
token.current.startLine <= position.line &&
|
|
||||||
token.current.startCol <= position.character &&
|
|
||||||
token.current.endLine >= position.line &&
|
|
||||||
token.current.endCol >= position.character,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache all locations of all open documents
|
// 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[]> {
|
async function onDefinition({ textDocument, position }: DefinitionParams): Promise<Location[]> {
|
||||||
connection.console.log('onDefinition event');
|
connection.console.log('onDefinition event');
|
||||||
const doc = documents.get(textDocument.uri);
|
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 [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = searchDefinition(position, doc.uri.replace('file://', ''), currentLocations);
|
const tokenLink = searchDefinition(position, doc.uri.replace('file://', ''), currentPage.links);
|
||||||
connection.console.log('found token: ' + JSON.stringify(token));
|
|
||||||
|
|
||||||
if (token == undefined) {
|
if (tokenLink == undefined) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const definition = token.definition;
|
const definition = tokenLink.definition;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -117,6 +133,7 @@ connection.onInitialize((params: InitializeParams) => {
|
|||||||
capabilities: {
|
capabilities: {
|
||||||
textDocumentSync: TextDocumentSyncKind.Full,
|
textDocumentSync: TextDocumentSyncKind.Full,
|
||||||
definitionProvider: true,
|
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)}`);
|
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.
|
// Send the computed diagnostics to VSCode.
|
||||||
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
|
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 { Diagnostic, DiagnosticSeverity, RemoteConsole } from 'vscode-languageserver/node';
|
||||||
import type { WorkspaceFolder } from 'vscode-languageserver-protocol';
|
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';
|
import type { Settings } from './settings';
|
||||||
|
|
||||||
@ -141,7 +147,7 @@ export async function compileAqua(
|
|||||||
textDocument: TextDocument,
|
textDocument: TextDocument,
|
||||||
folders: WorkspaceFolder[],
|
folders: WorkspaceFolder[],
|
||||||
console: RemoteConsole,
|
console: RemoteConsole,
|
||||||
): Promise<[Diagnostic[], TokenLink[]]> {
|
): Promise<[Diagnostic[], TokenLink[], TokenInfo[]]> {
|
||||||
const uri = textDocument.uri.replace('file://', '');
|
const uri = textDocument.uri.replace('file://', '');
|
||||||
|
|
||||||
const imports = getImports(settings, textDocument, folders, console);
|
const imports = getImports(settings, textDocument, folders, console);
|
||||||
@ -184,5 +190,5 @@ export async function compileAqua(
|
|||||||
|
|
||||||
const locations = result.locations.concat(links);
|
const locations = result.locations.concat(links);
|
||||||
|
|
||||||
return [diagnostics, locations];
|
return [diagnostics, locations, result.tokens];
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user