提交 e520a420 编写于 作者: M Martin Aeschlimann

fixes #7730: [json] Referencing **local** JSON schema from another local schema

上级 28ffb39e
......@@ -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#",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册