Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ The following settings are supported:
- `yaml.schemas`: Helps you associate schemas with files in a glob pattern
- `yaml.schemaStore.enable`: When set to true the YAML language server will pull in all available schemas from [JSON Schema Store](http://schemastore.org/json/)
- `yaml.customTags`: Array of custom tags that the parser will validate against. It has two ways to be used. Either an item in the array is a custom tag such as "!Ref" and it will automatically map !Ref to scalar or you can specify the type of the object !Ref should be e.g. "!Ref sequence". The type of object can be either scalar (for strings and booleans), sequence (for arrays), mapping (for objects).
- `[yaml]`: VSCode-YAML adds default configuration for all yaml files. More specifically it converts tabs to spaces to ensure valid yaml, sets the tab size, and allows live typing autocompletion and formatting. These settings can be modified via the corresponding settings inside the `[yaml]` section in the settings:
- `[yaml]`: VSCode-YAML adds default configuration for all yaml files. More specifically it converts tabs to spaces to ensure valid yaml, sets the tab size, and allows live typing autocompletion and formatting, also allows code lens. These settings can be modified via the corresponding settings inside the `[yaml]` section in the settings:
- `editor.insertSpaces`
- `editor.tabSize`
- `editor.quickSuggestions`
- `editor.formatOnType`
- `editor.codeLens`

##### Adding custom tags

Expand Down
5 changes: 4 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ export function activate(context: ExtensionContext): SchemaExtensionAPI {
// client can be deactivated on extension deactivation
context.subscriptions.push(disposable);
context.subscriptions.push(
workspace.registerTextDocumentContentProvider('json-schema', new JSONSchemaDocumentContentProvider(schemaCache))
workspace.registerTextDocumentContentProvider(
'json-schema',
new JSONSchemaDocumentContentProvider(schemaCache, schemaExtensionAPI)
)
);

findConflicts();
Expand Down
32 changes: 28 additions & 4 deletions src/json-schema-content-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,38 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { TextDocumentContentProvider, Uri, ProviderResult, workspace } from 'vscode';
import { TextDocumentContentProvider, Uri, workspace, window } from 'vscode';
import { xhr, configure as configureHttpRequests, getErrorStatusDescription, XHRResponse } from 'request-light';
import { JSONSchemaCache } from './json-schema-cache';
import { SchemaExtensionAPI } from './schema-extension-api';

export class JSONSchemaDocumentContentProvider implements TextDocumentContentProvider {
constructor(private readonly schemaCache: JSONSchemaCache) {}
provideTextDocumentContent(uri: Uri): ProviderResult<string> {
return getJsonSchemaContent(uri.toString().replace('json-schema://', 'https://'), this.schemaCache);
constructor(private readonly schemaCache: JSONSchemaCache, private readonly schemaApi: SchemaExtensionAPI) {}
async provideTextDocumentContent(uri: Uri): Promise<string> {
if (uri.fragment) {
const origUri = uri.fragment;
const schemaUri = Uri.parse(origUri);
// handle both 'http' and 'https'
if (origUri.startsWith('http')) {
return getJsonSchemaContent(origUri, this.schemaCache);
} else if (this.schemaApi.hasProvider(schemaUri.scheme)) {
let content = this.schemaApi.requestCustomSchemaContent(origUri);

content = await Promise.resolve(content);
// prettify JSON
if (content.indexOf('\n') === -1) {
content = JSON.stringify(JSON.parse(content), null, 2);
}

return content;
} else {
window.showErrorMessage(`Cannot Load content for: ${origUri}. Unknown schema: '${schemaUri.scheme}'`);
return null;
}
} else {
window.showErrorMessage(`Cannot Load content for: '${uri.toString()}' `);
return null;
}
}
}

Expand Down
8 changes: 6 additions & 2 deletions src/schema-extension-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { logToExtensionOutputChannel } from './extension';

interface SchemaContributorProvider {
readonly requestSchema: (resource: string) => string;
readonly requestSchemaContent: (uri: string) => string;
readonly requestSchemaContent: (uri: string) => Promise<string> | string;
readonly label?: string;
}

Expand Down Expand Up @@ -137,7 +137,7 @@ class SchemaExtensionAPI implements ExtensionAPI {
* @param {string} uri the schema uri returned from requestSchema.
* @returns {string} the schema content
*/
public requestCustomSchemaContent(uri: string): string {
public requestCustomSchemaContent(uri: string): Promise<string> | string {
if (uri) {
const _uri = URI.parse(uri);

Expand All @@ -154,6 +154,10 @@ class SchemaExtensionAPI implements ExtensionAPI {
public async modifySchemaContent(schemaModifications: SchemaAdditions | SchemaDeletions): Promise<void> {
return this._yamlClient.sendRequest(SchemaModificationNotification.type, schemaModifications);
}

public hasProvider(schema: string): boolean {
return this._customSchemaContributors[schema] !== undefined;
}
}

// constants
Expand Down
44 changes: 44 additions & 0 deletions test/json-shema-content-provider.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { getDocUri, activate } from './helper';
import * as assert from 'assert';

describe('Tests for JSON Schema content provider', () => {
const SCHEMA = 'myschema';
const schemaJSON = JSON.stringify({
type: 'object',
properties: {
version: {
type: 'string',
description: 'A stringy string string',
enum: ['test'],
},
},
});

function onRequestSchema1URI(resource: string): string | undefined {
if (resource.endsWith('completion.yaml') || resource.endsWith('basic.yaml')) {
return `${SCHEMA}://schema/porter`;
}
return undefined;
}

function onRequestSchema1Content(): string | undefined {
return schemaJSON;
}

it('should handle "json-schema" url', async () => {
const docUri = getDocUri('completion/completion.yaml');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you run this test against windows you might need ${path.sep}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, test on windows passed successfully

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

const client = await activate(docUri);
client._customSchemaContributors = {};
client.registerContributor(SCHEMA, onRequestSchema1URI, onRequestSchema1Content);
const customUri = vscode.Uri.parse(`json-schema://some/url/schema.json#${SCHEMA}://some/path/schema.json`);
const doc = await vscode.workspace.openTextDocument(customUri);
const editor = await vscode.window.showTextDocument(doc);
assert.strictEqual(editor.document.getText(), JSON.stringify(JSON.parse(schemaJSON), null, 2));
client._customSchemaContributors = {};
});
});