feat(aqua-vscode): Prettify types view [LNG-331] (#85)

This commit is contained in:
Dima 2024-02-21 09:13:14 +03:00 committed by GitHub
parent 0055ff0859
commit 56d4d41e6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 98 additions and 11 deletions

View File

@ -8,7 +8,7 @@
"name": "aqua-ls-server",
"version": "0.0.1",
"dependencies": {
"@fluencelabs/aqua-language-server-api": "0.14.0",
"@fluencelabs/aqua-language-server-api": "0.14.1",
"global-dirs": "^3.0.0",
"vscode-languageserver": "^7.0.0",
"vscode-languageserver-textdocument": "^1.0.4",
@ -35,9 +35,9 @@
"license": "Apache-2.0"
},
"node_modules/@fluencelabs/aqua-language-server-api": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.14.0.tgz",
"integrity": "sha512-q30OfMSiNIIFOC9Wvm1GaBpvxv7KsuiF7xej+juyGKa55Vo2cu/cl7Sl9FVsD2NZtWBHD7DmsmyqwAJyfnKbUw=="
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.14.1.tgz",
"integrity": "sha512-bLuSEziWqLhsbiVmS3IzYwsDuAsfQi2F8y9IS3/W+Nst9h872HmQ9nE52Ciqah/TALeqYK2L9o00ZYvr50cKhA=="
},
"node_modules/@types/json5": {
"version": "0.0.29",
@ -1289,9 +1289,9 @@
},
"dependencies": {
"@fluencelabs/aqua-language-server-api": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.14.0.tgz",
"integrity": "sha512-q30OfMSiNIIFOC9Wvm1GaBpvxv7KsuiF7xej+juyGKa55Vo2cu/cl7Sl9FVsD2NZtWBHD7DmsmyqwAJyfnKbUw=="
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.14.1.tgz",
"integrity": "sha512-bLuSEziWqLhsbiVmS3IzYwsDuAsfQi2F8y9IS3/W+Nst9h872HmQ9nE52Ciqah/TALeqYK2L9o00ZYvr50cKhA=="
},
"@types/json5": {
"version": "0.0.29",

View File

@ -11,7 +11,7 @@
"url": "https://github.com/fluencelabs/aqua"
},
"dependencies": {
"@fluencelabs/aqua-language-server-api": "0.14.0",
"@fluencelabs/aqua-language-server-api": "0.14.1",
"global-dirs": "^3.0.0",
"vscode-languageserver": "^7.0.0",
"vscode-languageserver-textdocument": "^1.0.4",
@ -25,4 +25,4 @@
"test": "ts-mocha",
"get-root": "npm root --global"
}
}
}

View File

@ -18,6 +18,7 @@ import { FluenceCli } from './cli';
import { Settings, SettingsManager } from './settings';
import { InfoManager } from './info';
import { tokenToLocation } from './utils';
import { typeToString } from './types';
// Create a connection to the server, using Node's IPC as a transport.
// Also include all preview / proposed LSP features.
@ -122,7 +123,8 @@ connection.onHover(({ textDocument, position }: HoverParams): Hover | null => {
const info = documentInfos.infoAt(textDocument.uri, position);
if (info) {
const content: MarkupContent = { kind: MarkupKind.PlainText, value: info.type };
const typeStr = typeToString(info.type);
const content: MarkupContent = { kind: MarkupKind.PlainText, value: typeStr };
return { contents: content };
}

View File

@ -7,6 +7,7 @@ import { Location, Position, Range } from 'vscode-languageserver';
import { compileAqua } from '../validation';
import { DocumentInfo } from '../info';
import { pathToUri, tokenToLocation } from '../utils';
import { ScalarType } from '@fluencelabs/aqua-language-server-api/aqua-lsp-api';
/**
* Load document from file, compile it and return info
@ -77,7 +78,10 @@ describe('DocumentInfo Test Suite', () => {
const info = docInfo.infoAt(pos);
assert.ok(info, 'Info not found');
assert.strictEqual(info.type, 'string', 'Wrong type info');
const type = info.type as ScalarType;
assert.strictEqual(type.tag, 'scalar', 'Wrong type tag');
assert.strictEqual(type.name, 'string', 'Wrong type');
}
}
});

81
server/src/types.ts Normal file
View File

@ -0,0 +1,81 @@
import type {
AbilityType,
ArrayType,
CanonStreamType,
OptionType,
ServiceType,
StreamMapType,
StreamType,
StructType,
Type,
} from '@fluencelabs/aqua-language-server-api/aqua-lsp-api';
const collectionPrefix = {
array: '[]',
stream: '*',
canon: '#',
streammap: '%',
option: '?',
};
function collectionToString(
type: ArrayType | StreamType | CanonStreamType | StreamMapType | OptionType,
depth: number,
) {
const elementType = typeToStringInner(type.element, depth);
const prefix = collectionPrefix[type.tag];
return prefix + elementType;
}
function namedToString(type: AbilityType | StructType | ServiceType, depth: number) {
let fieldsStr = Object.entries(type.fields).map(function ([name, fieldType]) {
const fieldTypeStr = typeToStringInner(fieldType, depth + 1);
return `${name}: ${fieldTypeStr}`;
});
return `${type.name}(${fieldsStr.join(', ')})`;
}
function typeToStringInner(type: Type, depth: number): string {
switch (type.tag) {
case 'nil':
return '∅';
case 'array':
case 'option':
case 'stream':
case 'streammap':
case 'canon':
return collectionToString(type, depth);
case 'struct':
case 'ability':
case 'service':
if (depth >= 1) {
return type.name;
}
return namedToString(type, depth);
case 'labeled':
const args = Object.entries(type.args).map(function ([name, argType]) {
const fieldTypeStr = typeToStringInner(argType, depth + 1);
return `${name}: ${fieldTypeStr}`;
});
return args.join(', ');
case 'unlabeled':
return type.types.map((t) => typeToStringInner(t, depth + 1)).join(', ');
case 'arrow':
const domainStr = typeToStringInner(type.domain, depth + 1);
const codomainStr = typeToStringInner(type.codomain, depth + 1);
return `func (${domainStr}) -> ${codomainStr}`;
case 'top':
return 'top';
case 'bottom':
return 'bottom';
case 'scalar':
return type.name;
default:
const _exhaustiveCheck: never = type;
return _exhaustiveCheck;
}
}
export function typeToString(type: Type): string {
return typeToStringInner(type, 0);
}