Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 116 additions & 19 deletions src/schema-status-bar-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ import {
import { CommonLanguageClient, RequestType } from 'vscode-languageclient/node';

type FileUri = string;
type SchemaVersions = { [version: string]: string };
interface JSONSchema {
name?: string;
description?: string;
uri: string;
versions?: SchemaVersions;
}

interface MatchingJSONSchema extends JSONSchema {
Expand All @@ -31,6 +33,11 @@ interface SchemaItem extends QuickPickItem {
schema?: MatchingJSONSchema;
}

interface SchemaVersionItem extends QuickPickItem {
version: string;
url: string;
}

// eslint-disable-next-line @typescript-eslint/ban-types
const getJSONSchemas: RequestType<FileUri, MatchingJSONSchema[], {}> = new RequestType('yaml/get/all/jsonSchemas');

Expand All @@ -40,6 +47,7 @@ const getSchema: RequestType<FileUri, JSONSchema[], {}> = new RequestType('yaml/
export let statusBarItem: StatusBarItem;

let client: CommonLanguageClient;
let versionSelection: SchemaItem = undefined;
export function createJSONSchemaStatusBarItem(context: ExtensionContext, languageclient: CommonLanguageClient): void {
if (statusBarItem) {
updateStatusBar(window.activeTextEditor);
Expand All @@ -61,6 +69,7 @@ export function createJSONSchemaStatusBarItem(context: ExtensionContext, languag

async function updateStatusBar(editor: TextEditor): Promise<void> {
if (editor && editor.document.languageId === 'yaml') {
versionSelection = undefined;
// get schema info there
const schema = await client.sendRequest(getSchema, editor.document.uri.toString());
if (!schema || schema.length === 0) {
Expand All @@ -69,6 +78,20 @@ async function updateStatusBar(editor: TextEditor): Promise<void> {
statusBarItem.backgroundColor = undefined;
} else if (schema.length === 1) {
statusBarItem.text = schema[0].name ?? schema[0].uri;
let version;
if (schema[0].versions) {
version = findUsedVersion(schema[0].versions, schema[0].uri);
} else {
const schemas = await client.sendRequest(getJSONSchemas, window.activeTextEditor.document.uri.toString());
let versionSchema: JSONSchema;
[version, versionSchema] = findSchemaStoreItem(schemas, schema[0].uri);
(versionSchema as MatchingJSONSchema).usedForCurrentFile = true;
versionSchema.uri = schema[0].uri;
versionSelection = createSelectVersionItem(version, versionSchema as MatchingJSONSchema);
}
if (version) {
statusBarItem.text += `(${version})`;
}
statusBarItem.tooltip = 'Select JSON Schema';
statusBarItem.backgroundColor = undefined;
} else {
Expand All @@ -86,9 +109,13 @@ async function updateStatusBar(editor: TextEditor): Promise<void> {
async function showSchemaSelection(): Promise<void> {
const schemas = await client.sendRequest(getJSONSchemas, window.activeTextEditor.document.uri.toString());
const schemasPick = window.createQuickPick<SchemaItem>();
const pickItems: SchemaItem[] = [];
let pickItems: SchemaItem[] = [];

for (const val of schemas) {
if (val.usedForCurrentFile && val.versions) {
const item = createSelectVersionItem(findUsedVersion(val.versions, val.uri), val);
pickItems.unshift(item);
}
const item = {
label: val.name ?? val.uri,
description: val.description,
Expand All @@ -98,8 +125,17 @@ async function showSchemaSelection(): Promise<void> {
};
pickItems.push(item);
}
if (versionSelection) {
pickItems.unshift(versionSelection);
}

pickItems.sort((a, b) => {
pickItems = pickItems.sort((a, b) => {
if (a.schema?.usedForCurrentFile && a.schema?.versions) {
return -1;
}
if (b.schema?.usedForCurrentFile && b.schema?.versions) {
return 1;
}
if (a.schema?.usedForCurrentFile) {
return -1;
}
Expand All @@ -117,23 +153,10 @@ async function showSchemaSelection(): Promise<void> {
schemasPick.onDidChangeSelection((selection) => {
try {
if (selection.length > 0) {
if (selection[0].schema) {
const settings: Record<string, unknown> = workspace.getConfiguration('yaml').get('schemas');
const fileUri = window.activeTextEditor.document.uri.toString();
const newSettings = Object.assign({}, settings);
deleteExistingFilePattern(newSettings, fileUri);
const schemaURI = selection[0].schema.uri;
const schemaSettings = newSettings[schemaURI];
if (schemaSettings) {
if (Array.isArray(schemaSettings)) {
(schemaSettings as Array<string>).push(fileUri);
} else if (typeof schemaSettings === 'string') {
newSettings[schemaURI] = [schemaSettings, fileUri];
}
} else {
newSettings[schemaURI] = fileUri;
}
workspace.getConfiguration('yaml').update('schemas', newSettings);
if (selection[0].label === 'Select Another Version') {
handleSchemaVersionSelection(selection[0].schema);
} else if (selection[0].schema) {
writeSchemaUriMapping(selection[0].schema.uri);
}
}
} catch (err) {
Expand Down Expand Up @@ -162,3 +185,77 @@ function deleteExistingFilePattern(settings: Record<string, unknown>, fileUri: s

return settings;
}

function createSelectVersionItem(version: string, schema: MatchingJSONSchema): SchemaItem {
return {
label: 'Select Another Version',
Comment thread
evidolob marked this conversation as resolved.
Outdated
detail: `Current: ${version}`,
alwaysShow: true,
schema: schema,
};
}
function findSchemaStoreItem(schemas: JSONSchema[], url: string): [string, JSONSchema] | undefined {
for (const schema of schemas) {
if (schema.versions) {
for (const version in schema.versions) {
if (url === schema.versions[version]) {
return [version, schema];
}
}
}
}
}

function writeSchemaUriMapping(schemaUrl: string): void {
const settings: Record<string, unknown> = workspace.getConfiguration('yaml').get('schemas');
const fileUri = window.activeTextEditor.document.uri.toString();
const newSettings = Object.assign({}, settings);
deleteExistingFilePattern(newSettings, fileUri);
const schemaSettings = newSettings[schemaUrl];
if (schemaSettings) {
if (Array.isArray(schemaSettings)) {
(schemaSettings as Array<string>).push(fileUri);
} else if (typeof schemaSettings === 'string') {
newSettings[schemaUrl] = [schemaSettings, fileUri];
}
} else {
newSettings[schemaUrl] = fileUri;
}
workspace.getConfiguration('yaml').update('schemas', newSettings);
}

function handleSchemaVersionSelection(schema: MatchingJSONSchema): void {
const versionPick = window.createQuickPick<SchemaVersionItem>();
const versionItems: SchemaVersionItem[] = [];
const usedVersion = findUsedVersion(schema.versions, schema.uri);
for (const version in schema.versions) {
versionItems.push({
label: version + (usedVersion === version ? '$(check)' : ''),
url: schema.versions[version],
version: version,
});
}

versionPick.items = versionItems;
versionPick.title = `Select JSON Schema version for ${schema.name}`;
versionPick.placeholder = 'Version';
versionPick.onDidHide(() => versionPick.dispose());

versionPick.onDidChangeSelection((items) => {
if (items && items.length === 1) {
writeSchemaUriMapping(items[0].url);
}
versionPick.hide();
});
versionPick.show();
}

function findUsedVersion(versions: SchemaVersions, uri: string): string {
for (const version in versions) {
const versionUri = versions[version];
if (versionUri === uri) {
return version;
}
}
return 'latest';
}