fixes #5334: [json] swagger 2.0 json schema not working for intellisense in visual studio code

This commit is contained in:
Martin Aeschlimann 2016-04-21 20:10:14 +02:00
parent 63e77984e7
commit 42a2cd5665
4 changed files with 154 additions and 41 deletions

View file

@ -5,7 +5,7 @@
'use strict';
import Json = require('jsonc-parser');
import {IJSONSchema} from './jsonSchema';
import {IJSONSchema, IJSONSchemaMap} from './jsonSchema';
import {XHROptions, XHRResponse, getErrorStatusDescription} from 'request-light';
import URI from './utils/uri';
import Strings = require('./utils/strings');
@ -411,36 +411,54 @@ export class JSONSchemaService implements IJSONSchemaService {
});
};
let resolveRefs = (node: any, parentSchema: any): Thenable<any> => {
let toWalk = [node];
let seen: any[] = [];
let resolveRefs = (node: IJSONSchema, parentSchema: IJSONSchema): Thenable<any> => {
let toWalk : IJSONSchema[] = [node];
let seen: IJSONSchema[] = [];
let openPromises: Thenable<any>[] = [];
let collectEntries = (...entries: IJSONSchema[]) => {
for (let entry of entries) {
if (typeof entry === 'object') {
toWalk.push(entry);
}
}
};
let collectMapEntries = (...maps: IJSONSchemaMap[]) => {
for (let map of maps) {
if (typeof map === 'object') {
for (let key in map) {
let entry = map[key];
toWalk.push(entry);
}
}
}
};
let collectArrayEntries = (...arrays: IJSONSchema[][]) => {
for (let array of arrays) {
if (Array.isArray(array)) {
toWalk.push.apply(toWalk, array);
}
}
};
while (toWalk.length) {
let next = toWalk.pop();
if (seen.indexOf(next) >= 0) {
continue;
}
seen.push(next);
if (Array.isArray(next)) {
next.forEach(item => {
toWalk.push(item);
});
} else if (next) {
if (next.$ref) {
let segments = next.$ref.split('#', 2);
if (segments[0].length > 0) {
openPromises.push(resolveExternalLink(next, segments[0], segments[1]));
continue;
} else {
resolveLink(next, parentSchema, segments[1]);
}
}
for (let key in next) {
toWalk.push(next[key]);
if (next.$ref) {
let segments = next.$ref.split('#', 2);
if (segments[0].length > 0) {
openPromises.push(resolveExternalLink(next, segments[0], segments[1]));
continue;
} else {
resolveLink(next, parentSchema, segments[1]);
}
}
collectEntries(next.items, next.additionalProperties, next.not);
collectMapEntries(next.definitions, next.properties, next.patternProperties, <IJSONSchemaMap> next.dependencies);
collectArrayEntries(next.anyOf, next.allOf, next.oneOf, <IJSONSchema[]> next.items);
}
return Promise.all(openPromises);
};

View file

@ -73,6 +73,44 @@ suite('JSON Schema', () => {
});
});
test('Resolving $refs 2', function(testDone) {
var service = new SchemaService.JSONSchemaService(requestServiceMock);
service.setSchemaContributions({ schemas: {
"http://json.schemastore.org/swagger-2.0" : {
id: 'http://json.schemastore.org/swagger-2.0',
type: 'object',
properties: {
"responseValue": {
"$ref": "#/definitions/jsonReference"
}
},
definitions: {
"jsonReference": {
"type": "object",
"required": [ "$ref" ],
"properties": {
"$ref": {
"type": "string"
}
}
}
}
}
}
});
service.getResolvedSchema('http://json.schemastore.org/swagger-2.0').then(fs => {
assert.deepEqual(fs.schema.properties['responseValue'], {
type: 'object',
required: [ "$ref" ],
properties: { $ref: { type: 'string' }}
});
}).then(() => testDone(), (error) => {
testDone(error);
});
});
test('FileSchema', function(testDone) {
var service = new SchemaService.JSONSchemaService(requestServiceMock);

View file

@ -9,7 +9,7 @@ import nls = require('vs/nls');
import Objects = require('vs/base/common/objects');
import Json = require('vs/base/common/json');
import http = require('vs/base/common/http');
import {IJSONSchema} from 'vs/base/common/jsonSchema';
import {IJSONSchema, IJSONSchemaMap} from 'vs/base/common/jsonSchema';
import Strings = require('vs/base/common/strings');
import URI from 'vs/base/common/uri';
import Types = require('vs/base/common/types');
@ -392,37 +392,56 @@ export class JSONSchemaService implements IJSONSchemaService {
});
};
var resolveRefs = (node:any, parentSchema: any) : WinJS.Promise => {
var toWalk = [ node ];
var seen: any[] = [];
let resolveRefs = (node: IJSONSchema, parentSchema: IJSONSchema): WinJS.Promise => {
let toWalk : IJSONSchema[] = [node];
let seen: IJSONSchema[] = [];
var openPromises: WinJS.Promise[] = [];
let collectEntries = (...entries: IJSONSchema[]) => {
for (let entry of entries) {
if (typeof entry === 'object') {
toWalk.push(entry);
}
}
};
let collectMapEntries = (...maps: IJSONSchemaMap[]) => {
for (let map of maps) {
if (typeof map === 'object') {
for (let key in map) {
let entry = map[key];
toWalk.push(entry);
}
}
}
};
let collectArrayEntries = (...arrays: IJSONSchema[][]) => {
for (let array of arrays) {
if (Array.isArray(array)) {
toWalk.push.apply(toWalk, array);
}
}
};
while (toWalk.length) {
var next = toWalk.pop();
let next = toWalk.pop();
if (seen.indexOf(next) >= 0) {
continue;
}
seen.push(next);
if (Array.isArray(next)) {
next.forEach(item => {
toWalk.push(item);
});
} else if (Types.isObject(next)) {
if (next.$ref) {
var segments = next.$ref.split('#', 2);
if (segments[0].length > 0) {
openPromises.push(resolveExternalLink(next, segments[0], segments[1]));
continue;
} else {
resolveLink(next, parentSchema, segments[1]);
}
}
for (var key in next) {
toWalk.push(next[key]);
if (next.$ref) {
let segments = next.$ref.split('#', 2);
if (segments[0].length > 0) {
openPromises.push(resolveExternalLink(next, segments[0], segments[1]));
continue;
} else {
resolveLink(next, parentSchema, segments[1]);
}
}
collectEntries(next.items, next.additionalProperties, next.not);
collectMapEntries(next.definitions, next.properties, next.patternProperties, <IJSONSchemaMap> next.dependencies);
collectArrayEntries(next.anyOf, next.allOf, next.oneOf, <IJSONSchema[]> next.items);
}
return WinJS.Promise.join(openPromises);
};

View file

@ -79,6 +79,44 @@ suite('JSON - schema', () => {
});
test('Resolving $refs 2', function(testDone) {
var service = new SchemaService.JSONSchemaService(requestServiceMock);
service.setSchemaContributions({ schemas: {
"http://json.schemastore.org/swagger-2.0" : {
id: 'http://json.schemastore.org/swagger-2.0',
type: 'object',
properties: {
"responseValue": {
"$ref": "#/definitions/jsonReference"
}
},
definitions: {
"jsonReference": {
"type": "object",
"required": [ "$ref" ],
"properties": {
"$ref": {
"type": "string"
}
}
}
}
}
}
});
service.getResolvedSchema('http://json.schemastore.org/swagger-2.0').then(fs => {
assert.deepEqual(fs.schema.properties['responseValue'], {
type: 'object',
required: [ "$ref" ],
properties: { $ref: { type: 'string' }}
});
}).then(() => testDone(), (error) => {
testDone(error);
});
});
test('FileSchema', function(testDone) {
var service = new SchemaService.JSONSchemaService(requestServiceMock);