mirror of
https://github.com/fluencelabs/aqua-vscode
synced 2025-04-25 00:22:15 +00:00
Rewrite imports handling (#73)
This commit is contained in:
parent
60bd5335b5
commit
3fad69ba77
45
package.json
45
package.json
@ -63,9 +63,48 @@
|
||||
"title": "Aqua",
|
||||
"properties": {
|
||||
"aquaSettings.imports": {
|
||||
"definitions": {
|
||||
"legacyImports": {
|
||||
"description": "Legacy format of imports - just an array of paths",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"structuredImports": {
|
||||
"description": "Structured format of imports - dict of settings for path prefixes",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"description": "Settings for path prefix - dict of locations for import prefixes",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"description": "Location for import prefix",
|
||||
"type": [
|
||||
"string",
|
||||
"array"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scope": "resource",
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"type": [
|
||||
"object",
|
||||
"array"
|
||||
],
|
||||
"if": {
|
||||
"type": "object"
|
||||
},
|
||||
"then": {
|
||||
"$ref": "#/definitions/structuredImports"
|
||||
},
|
||||
"else": {
|
||||
"$ref": "#/definitions/legacyImports"
|
||||
},
|
||||
"default": {},
|
||||
"description": "Adds imports for aqua file or project"
|
||||
},
|
||||
"aquaSettings.enableLegacyAutoImportSearch": {
|
||||
@ -115,4 +154,4 @@
|
||||
"prettier": "2.6.2",
|
||||
"typescript": "^4.6.3"
|
||||
}
|
||||
}
|
||||
}
|
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.1",
|
||||
"@fluencelabs/aqua-language-server-api": "0.13.2",
|
||||
"global-dirs": "^3.0.0",
|
||||
"vscode-languageserver": "^7.0.0",
|
||||
"vscode-languageserver-textdocument": "^1.0.4",
|
||||
@ -31,9 +31,9 @@
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@fluencelabs/aqua-language-server-api": {
|
||||
"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=="
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.13.2.tgz",
|
||||
"integrity": "sha512-hvq4/pB4kPx9t8z9NwM0BYxcXDtyN6h+SS4dmmZ/wSSLIEVWglKDc8R/JXAky96sPwdr1zNrNpNTnH0Ta9xJpw=="
|
||||
},
|
||||
"node_modules/global-dirs": {
|
||||
"version": "3.0.0",
|
||||
@ -103,9 +103,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fluencelabs/aqua-language-server-api": {
|
||||
"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=="
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@fluencelabs/aqua-language-server-api/-/aqua-language-server-api-0.13.2.tgz",
|
||||
"integrity": "sha512-hvq4/pB4kPx9t8z9NwM0BYxcXDtyN6h+SS4dmmZ/wSSLIEVWglKDc8R/JXAky96sPwdr1zNrNpNTnH0Ta9xJpw=="
|
||||
},
|
||||
"global-dirs": {
|
||||
"version": "3.0.0",
|
||||
|
@ -11,7 +11,7 @@
|
||||
"url": "https://github.com/fluencelabs/aqua"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fluencelabs/aqua-language-server-api": "0.13.1",
|
||||
"@fluencelabs/aqua-language-server-api": "0.13.2",
|
||||
"global-dirs": "^3.0.0",
|
||||
"vscode-languageserver": "^7.0.0",
|
||||
"vscode-languageserver-textdocument": "^1.0.4",
|
||||
@ -20,4 +20,4 @@
|
||||
"scripts": {
|
||||
"get-root": "npm root --global"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
import { exec } from 'child_process';
|
||||
import { dirname } from 'path';
|
||||
|
||||
import type { Imports } from './imports';
|
||||
import { normalizeImports } from './imports';
|
||||
|
||||
export class FluenceCli {
|
||||
readonly cliPath: string;
|
||||
|
||||
@ -16,13 +19,17 @@ export class FluenceCli {
|
||||
* Returns output of `fluence aqua imports`
|
||||
* in dir of @param filePath.
|
||||
*/
|
||||
async imports(filePath: string): Promise<string[]> {
|
||||
async imports(filePath: string): Promise<Imports> {
|
||||
const cwd = dirname(filePath);
|
||||
const result = await this.runJson(['aqua', 'imports'], cwd);
|
||||
if (Array.isArray(result) && result.every((i) => typeof i === 'string')) {
|
||||
return result;
|
||||
} else {
|
||||
throw new Error(`Invalid result: ${JSON.stringify(result)}`);
|
||||
try {
|
||||
return normalizeImports(result);
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error(`Error converting imports from fluence: ${e.message}`);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
61
server/src/imports.ts
Normal file
61
server/src/imports.ts
Normal file
@ -0,0 +1,61 @@
|
||||
export type Imports = Record<string, Record<string, string[]>>;
|
||||
|
||||
// Normalize imports to the new format
|
||||
// Legacy format of an array of paths is converted to the new format
|
||||
// Empty imports are converted to an empty object
|
||||
export function normalizeImports(imports: unknown): Imports {
|
||||
console.log('normalizeImports: ', imports);
|
||||
// Empty imports
|
||||
if (imports === undefined || imports === null) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Legacy imports - array of paths
|
||||
if (Array.isArray(imports) && imports.every((i) => typeof i === 'string')) {
|
||||
return {
|
||||
'/': {
|
||||
'': imports as string[],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const isStringArray = (v: unknown): v is string[] => {
|
||||
return Array.isArray(v) && v.every((i) => typeof i === 'string');
|
||||
};
|
||||
|
||||
// New imports - object of objects of paths or arrays of paths
|
||||
// Inner single paths are normalized to arrays
|
||||
if (typeof imports === 'object') {
|
||||
for (const info of Object.values(imports)) {
|
||||
if (typeof info !== 'object') {
|
||||
throw new Error(`Invalid imports: ${JSON.stringify(imports)}`);
|
||||
}
|
||||
|
||||
for (const [importPrefix, locations] of Object.entries(info)) {
|
||||
if (typeof locations === 'string') {
|
||||
info[importPrefix] = [locations];
|
||||
} else if (!isStringArray(locations)) {
|
||||
throw new Error(`Invalid imports: ${JSON.stringify(imports)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return imports as Imports;
|
||||
}
|
||||
|
||||
throw new Error(`Invalid imports: ${JSON.stringify(imports)}`);
|
||||
}
|
||||
|
||||
// Deep merge two import settings, overriding the first with the second
|
||||
export function uniteImports(pre: Imports, post: Imports): Imports {
|
||||
const result: Imports = { ...pre };
|
||||
for (const [importPrefix, locations] of Object.entries(post)) {
|
||||
if (importPrefix in result) {
|
||||
result[importPrefix] = { ...result[importPrefix], ...locations };
|
||||
} else {
|
||||
result[importPrefix] = locations;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
import type { Configuration } from 'vscode-languageserver/lib/common/configuration';
|
||||
import { URI } from 'vscode-uri';
|
||||
|
||||
import type { Imports } from './imports';
|
||||
import { normalizeImports, uniteImports } from './imports';
|
||||
import type { FluenceCli } from './cli';
|
||||
|
||||
type Imports = string[];
|
||||
|
||||
export interface Settings {
|
||||
imports: Imports;
|
||||
enableLegacyAutoImportSearch: boolean;
|
||||
@ -17,7 +17,7 @@ class DocumentInfo {
|
||||
/* Settings from configuration (or default) */
|
||||
private settings: Settings;
|
||||
/* Additional imports from CLI */
|
||||
private imports: Imports = [];
|
||||
private imports: Imports = {};
|
||||
private importsLastUpdated = 0;
|
||||
private importsUpdateRequested = true;
|
||||
|
||||
@ -28,7 +28,8 @@ class DocumentInfo {
|
||||
getSettings(): Settings {
|
||||
return {
|
||||
...this.settings,
|
||||
imports: [...this.settings.imports, ...this.imports],
|
||||
// Imports from settings override imports from CLI
|
||||
imports: uniteImports(this.imports, this.settings.imports),
|
||||
};
|
||||
}
|
||||
|
||||
@ -43,7 +44,7 @@ class DocumentInfo {
|
||||
return isUpdateReady && this.importsUpdateRequested;
|
||||
}
|
||||
|
||||
updateImports(imports: string[]) {
|
||||
updateImports(imports: Imports) {
|
||||
this.imports = imports;
|
||||
this.importsLastUpdated = Date.now();
|
||||
this.importsUpdateRequested = false;
|
||||
@ -61,7 +62,7 @@ export interface SettingsManagerConfig {
|
||||
*/
|
||||
export class SettingsManager {
|
||||
private readonly defaultSettings: Settings = {
|
||||
imports: [],
|
||||
imports: {},
|
||||
enableLegacyAutoImportSearch: false,
|
||||
};
|
||||
private documents: Map<string, DocumentInfo> = new Map();
|
||||
@ -149,6 +150,15 @@ export class SettingsManager {
|
||||
section: 'aquaSettings',
|
||||
});
|
||||
if (settings) {
|
||||
try {
|
||||
settings.imports = normalizeImports(settings.imports);
|
||||
} catch (e) {
|
||||
// TODO: Maybe show some notification to user?
|
||||
// Don't know how to handle it better.
|
||||
console.error('Cannot normalize imports from settings: ', e);
|
||||
settings.imports = {};
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user