mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-26 03:29:00 +01:00
fixes #7730: [json] Referencing **local** JSON schema from another local schema
This commit is contained in:
@@ -128,7 +128,7 @@ class SchemaHandle implements ISchemaHandle {
|
||||
public getResolvedSchema(): Thenable<ResolvedSchema> {
|
||||
if (!this.resolvedSchema) {
|
||||
this.resolvedSchema = this.getUnresolvedSchema().then(unresolved => {
|
||||
return this.service.resolveSchemaContent(unresolved);
|
||||
return this.service.resolveSchemaContent(unresolved, this.url);
|
||||
});
|
||||
}
|
||||
return this.resolvedSchema;
|
||||
@@ -357,17 +357,21 @@ export class JSONSchemaService implements IJSONSchemaService {
|
||||
);
|
||||
}
|
||||
|
||||
public resolveSchemaContent(schemaToResolve: UnresolvedSchema): Thenable<ResolvedSchema> {
|
||||
public resolveSchemaContent(schemaToResolve: UnresolvedSchema, schemaURL: string): Thenable<ResolvedSchema> {
|
||||
|
||||
let resolveErrors: string[] = schemaToResolve.errors.slice(0);
|
||||
let schema = schemaToResolve.schema;
|
||||
let contextService = this.contextService;
|
||||
|
||||
let findSection = (schema: IJSONSchema, path: string): any => {
|
||||
if (!path) {
|
||||
return schema;
|
||||
}
|
||||
let current: any = schema;
|
||||
path.substr(1).split('/').some((part) => {
|
||||
if (path[0] === '/') {
|
||||
path = path.substr(1);
|
||||
}
|
||||
path.split('/').some((part) => {
|
||||
current = current[part];
|
||||
return !current;
|
||||
});
|
||||
@@ -388,18 +392,21 @@ export class JSONSchemaService implements IJSONSchemaService {
|
||||
delete node.$ref;
|
||||
};
|
||||
|
||||
let resolveExternalLink = (node: any, uri: string, linkPath: string): Thenable<any> => {
|
||||
let resolveExternalLink = (node: any, uri: string, linkPath: string, parentSchemaURL: string): Thenable<any> => {
|
||||
if (contextService && !/^\w+:\/\/.*/.test(uri)) {
|
||||
uri = contextService.resolveRelativePath(uri, parentSchemaURL);
|
||||
}
|
||||
return this.getOrAddSchemaHandle(uri).getUnresolvedSchema().then(unresolvedSchema => {
|
||||
if (unresolvedSchema.errors.length) {
|
||||
let loc = linkPath ? uri + '#' + linkPath : uri;
|
||||
resolveErrors.push(localize('json.schema.problemloadingref', 'Problems loading reference \'{0}\': {1}', loc, unresolvedSchema.errors[0]));
|
||||
}
|
||||
resolveLink(node, unresolvedSchema.schema, linkPath);
|
||||
return resolveRefs(node, unresolvedSchema.schema);
|
||||
return resolveRefs(node, unresolvedSchema.schema, uri);
|
||||
});
|
||||
};
|
||||
|
||||
let resolveRefs = (node: IJSONSchema, parentSchema: IJSONSchema): Thenable<any> => {
|
||||
let resolveRefs = (node: IJSONSchema, parentSchema: IJSONSchema, parentSchemaURL: string): Thenable<any> => {
|
||||
let toWalk : IJSONSchema[] = [node];
|
||||
let seen: IJSONSchema[] = [];
|
||||
|
||||
@@ -438,7 +445,7 @@ export class JSONSchemaService implements IJSONSchemaService {
|
||||
if (next.$ref) {
|
||||
let segments = next.$ref.split('#', 2);
|
||||
if (segments[0].length > 0) {
|
||||
openPromises.push(resolveExternalLink(next, segments[0], segments[1]));
|
||||
openPromises.push(resolveExternalLink(next, segments[0], segments[1], parentSchemaURL));
|
||||
continue;
|
||||
} else {
|
||||
resolveLink(next, parentSchema, segments[1]);
|
||||
@@ -451,7 +458,7 @@ export class JSONSchemaService implements IJSONSchemaService {
|
||||
return Promise.all(openPromises);
|
||||
};
|
||||
|
||||
return resolveRefs(schema, schema).then(_ => new ResolvedSchema(schema, resolveErrors));
|
||||
return resolveRefs(schema, schema, schemaURL).then(_ => new ResolvedSchema(schema, resolveErrors));
|
||||
}
|
||||
|
||||
public getSchemaForResource(resource: string, document: Parser.JSONDocument): Thenable<ResolvedSchema> {
|
||||
|
||||
@@ -13,6 +13,7 @@ import {xhr, XHROptions, XHRResponse, configure as configureHttpRequests} from '
|
||||
import path = require('path');
|
||||
import fs = require('fs');
|
||||
import URI from './utils/uri';
|
||||
import * as URL from 'url';
|
||||
import Strings = require('./utils/strings');
|
||||
import {ISchemaAssociations} from './jsonSchemaService';
|
||||
import {JSONDocument} from './jsonParser';
|
||||
@@ -71,11 +72,7 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
|
||||
|
||||
let workspaceContext = {
|
||||
resolveRelativePath: (relativePath: string, resource: string) => {
|
||||
if (typeof relativePath === 'string' && resource) {
|
||||
let resourceURI = URI.parse(resource);
|
||||
return URI.file(path.normalize(path.join(path.dirname(resourceURI.fsPath), relativePath))).toString();
|
||||
}
|
||||
return void 0;
|
||||
return URL.resolve(resource, relativePath);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import JsonSchema = require('../jsonSchema');
|
||||
import Json = require('jsonc-parser');
|
||||
import Parser = require('../jsonParser');
|
||||
import fs = require('fs');
|
||||
import url = require('url');
|
||||
import path = require('path');
|
||||
import {XHROptions, XHRResponse} from 'request-light';
|
||||
|
||||
@@ -43,8 +44,14 @@ suite('JSON Schema', () => {
|
||||
return Promise.reject<XHRResponse>({ responseText: '', status: 404 });
|
||||
}
|
||||
|
||||
let workspaceContext = {
|
||||
resolveRelativePath: (relativePath: string, resource: string) => {
|
||||
return url.resolve(resource, relativePath);
|
||||
}
|
||||
};
|
||||
|
||||
test('Resolving $refs', function(testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
service.setSchemaContributions({ schemas: {
|
||||
"https://myschemastore/main" : {
|
||||
id: 'https://myschemastore/main',
|
||||
@@ -73,9 +80,9 @@ suite('JSON Schema', () => {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
test('Resolving $refs 2', function(testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
service.setSchemaContributions({ schemas: {
|
||||
"http://json.schemastore.org/swagger-2.0" : {
|
||||
id: 'http://json.schemastore.org/swagger-2.0',
|
||||
@@ -112,8 +119,56 @@ suite('JSON Schema', () => {
|
||||
|
||||
});
|
||||
|
||||
test('Resolving $refs 3', function(testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
service.setSchemaContributions({ schemas: {
|
||||
"https://myschemastore/main/schema1.json" : {
|
||||
id: 'https://myschemastore/schema1.json',
|
||||
type: 'object',
|
||||
properties: {
|
||||
p1: {
|
||||
'$ref': 'schema2.json#/definitions/hello'
|
||||
},
|
||||
p2: {
|
||||
'$ref': './schema2.json#/definitions/hello'
|
||||
},
|
||||
p3: {
|
||||
'$ref': '/main/schema2.json#/definitions/hello'
|
||||
}
|
||||
}
|
||||
},
|
||||
"https://myschemastore/main/schema2.json" :{
|
||||
id: 'https://myschemastore/main/schema2.json',
|
||||
definitions: {
|
||||
"hello": {
|
||||
"type": "string",
|
||||
"enum": [ "object" ],
|
||||
}
|
||||
}
|
||||
}
|
||||
}});
|
||||
|
||||
service.getResolvedSchema('https://myschemastore/main/schema1.json').then(fs => {
|
||||
assert.deepEqual(fs.schema.properties['p1'], {
|
||||
type: 'string',
|
||||
enum: [ "object" ]
|
||||
});
|
||||
assert.deepEqual(fs.schema.properties['p2'], {
|
||||
type: 'string',
|
||||
enum: [ "object" ]
|
||||
});
|
||||
assert.deepEqual(fs.schema.properties['p3'], {
|
||||
type: 'string',
|
||||
enum: [ "object" ]
|
||||
});
|
||||
}).then(() => testDone(), (error) => {
|
||||
testDone(error);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('FileSchema', function(testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
|
||||
service.setSchemaContributions({ schemas: {
|
||||
"main" : {
|
||||
@@ -142,7 +197,7 @@ suite('JSON Schema', () => {
|
||||
});
|
||||
|
||||
test('Array FileSchema', function(testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
|
||||
service.setSchemaContributions({ schemas: {
|
||||
"main" : {
|
||||
@@ -174,7 +229,7 @@ suite('JSON Schema', () => {
|
||||
});
|
||||
|
||||
test('Missing subschema', function(testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
|
||||
service.setSchemaContributions({ schemas: {
|
||||
"main" : {
|
||||
@@ -197,7 +252,7 @@ suite('JSON Schema', () => {
|
||||
});
|
||||
|
||||
test('Preloaded Schema', function(testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
var id = 'https://myschemastore/test1';
|
||||
var schema : JsonSchema.IJSONSchema = {
|
||||
type: 'object',
|
||||
@@ -225,7 +280,7 @@ suite('JSON Schema', () => {
|
||||
});
|
||||
|
||||
test('External Schema', function(testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
var id = 'https://myschemastore/test1';
|
||||
var schema : JsonSchema.IJSONSchema = {
|
||||
type: 'object',
|
||||
@@ -254,7 +309,7 @@ suite('JSON Schema', () => {
|
||||
|
||||
|
||||
test('Resolving in-line $refs', function (testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
var id = 'https://myschemastore/test1';
|
||||
|
||||
var schema:JsonSchema.IJSONSchema = {
|
||||
@@ -292,7 +347,7 @@ suite('JSON Schema', () => {
|
||||
});
|
||||
|
||||
test('Resolving in-line $refs automatically for external schemas', function(testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
var id = 'https://myschemastore/test1';
|
||||
var schema:JsonSchema.IJSONSchema = {
|
||||
id: 'main',
|
||||
@@ -329,7 +384,7 @@ suite('JSON Schema', () => {
|
||||
|
||||
|
||||
test('Clearing External Schemas', function(testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
var id1 = 'http://myschemastore/test1';
|
||||
var schema1:JsonSchema.IJSONSchema = {
|
||||
type: 'object',
|
||||
@@ -370,7 +425,7 @@ suite('JSON Schema', () => {
|
||||
});
|
||||
|
||||
test('Schema contributions', function(testDone) {
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
|
||||
service.setSchemaContributions({ schemas: {
|
||||
"http://myschemastore/myschemabar" : {
|
||||
@@ -420,7 +475,7 @@ suite('JSON Schema', () => {
|
||||
|
||||
test('Resolving circular $refs', function(testDone) {
|
||||
|
||||
var service : SchemaService.IJSONSchemaService = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service : SchemaService.IJSONSchemaService = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
|
||||
var input = {
|
||||
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
@@ -463,7 +518,7 @@ suite('JSON Schema', () => {
|
||||
|
||||
test('Resolving circular $refs, invalid document', function(testDone) {
|
||||
|
||||
var service : SchemaService.IJSONSchemaService = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service : SchemaService.IJSONSchemaService = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
|
||||
var input = {
|
||||
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
@@ -498,7 +553,7 @@ suite('JSON Schema', () => {
|
||||
test('Validate Azure Resource Dfinition', function(testDone) {
|
||||
|
||||
|
||||
var service : SchemaService.IJSONSchemaService = new SchemaService.JSONSchemaService(requestServiceMock);
|
||||
var service : SchemaService.IJSONSchemaService = new SchemaService.JSONSchemaService(requestServiceMock, workspaceContext);
|
||||
|
||||
var input = {
|
||||
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
|
||||
Reference in New Issue
Block a user