public resolveSchemaContent()

in language-service/src/services/jsonSchemaService.ts [388:495]


	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: JSONSchema, path: string): any => {
			if (!path) {
				return schema;
			}
			let current: any = schema;
			if (path[0] === '/') {
				path = path.substr(1);
			}
			path.split('/').some((part) => {
				current = current[part];
				return !current;
			});
			return current;
		};

		let resolveLink = (node: any, linkedSchema: JSONSchema, linkPath: string): void => {
			let section = findSection(linkedSchema, linkPath);
			if (section) {
				for (let key in section) {
					if (section.hasOwnProperty(key) && !node.hasOwnProperty(key)) {
						node[key] = section[key];
					}
				}
			} else {
				resolveErrors.push(localize('json.schema.invalidref', '$ref \'{0}\' in {1} can not be resolved.', linkPath, linkedSchema.id));
			}
			delete node.$ref;
		};

		let resolveExternalLink = (node: any, uri: string, linkPath: string, parentSchemaURL: string): Thenable<any> => {
			if (contextService && !/^\w+:\/\/.*/.test(uri)) {
				uri = contextService.resolveRelativePath(uri, parentSchemaURL);
			}
			uri = this.normalizeId(uri);
			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, uri);
			});
		};

		let resolveRefs = (node: JSONSchema, parentSchema: JSONSchema, parentSchemaURL: string): Thenable<any> => {
			if (!node) {
				return Promise.resolve(null);
			}

			let toWalk: JSONSchema[] = [node];
			let seen: JSONSchema[] = [];

			let openPromises: Thenable<any>[] = [];

			let collectEntries = (...entries: JSONSchema[]) => {
				for (let entry of entries) {
					if (typeof entry === 'object') {
						toWalk.push(entry);
					}
				}
			};
			let collectMapEntries = (...maps: JSONSchemaMap[]) => {
				for (let map of maps) {
					if (typeof map === 'object') {
						for (let key in map) {
							let entry = map[key];
							toWalk.push(entry);
						}
					}
				}
			};
			let collectArrayEntries = (...arrays: JSONSchema[][]) => {
				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 (next.$ref) {
					let segments = next.$ref.split('#', 2);
					if (segments[0].length > 0) {
						openPromises.push(resolveExternalLink(next, segments[0], segments[1], parentSchemaURL));
						continue;
					} else {
						resolveLink(next, parentSchema, segments[1]);
					}
				}
				collectEntries(next.items, next.additionalProperties, next.not);
				collectMapEntries(next.definitions, next.properties, next.patternProperties, <JSONSchemaMap>next.dependencies);
				collectArrayEntries(next.anyOf, next.allOf, next.oneOf, <JSONSchema[]>next.items);
			}
			return this.promise.all(openPromises);
		};

		return resolveRefs(schema, schema, schemaURL).then(_ => new ResolvedSchema(schema, resolveErrors));
	}