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
33 changes: 28 additions & 5 deletions src/parser/jsonParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { JSONSchema, JSONSchemaRef } from '../jsonSchema';
import { isNumber, equals, isBoolean, isString, isDefined, isObject } from '../utils/objects';
import { extendedRegExp, stringLength } from '../utils/strings';
import { TextDocument, ASTNode, ObjectASTNode, ArrayASTNode, BooleanASTNode, NumberASTNode, StringASTNode, NullASTNode, PropertyASTNode, JSONPath, ErrorCode, Diagnostic, DiagnosticSeverity, Range, SchemaDraft } from '../jsonLanguageTypes';
import { URI } from 'vscode-uri';

import * as l10n from '@vscode/l10n';

Expand Down Expand Up @@ -171,11 +172,33 @@ export enum EnumMatch {
Key, Enum
}

const httpPrefix = `http://json-schema.org/`;
const httpsPrefix = `https://json-schema.org/`;

export function normalizeId(id: string): string {
// use the https prefix for the old json-schema.org meta schemas
// See https://github.com/microsoft/vscode/issues/195189
if (id.startsWith(httpPrefix)) {
id = httpsPrefix + id.substring(httpPrefix.length);
}
// remove trailing '#', normalize drive capitalization
try {
return URI.parse(id).toString(true);
} catch (e) {
return id;
}

}

export function getSchemaDraftFromId(schemaId: string): SchemaDraft | undefined {
return schemaDraftFromId[normalizeId(schemaId)] ?? undefined;
}

const schemaDraftFromId: { [id: string]: SchemaDraft } = {
'http://json-schema.org/draft-03/schema#': SchemaDraft.v3,
'http://json-schema.org/draft-04/schema#': SchemaDraft.v4,
'http://json-schema.org/draft-06/schema#': SchemaDraft.v6,
'http://json-schema.org/draft-07/schema#': SchemaDraft.v7,
'https://json-schema.org/draft-03/schema': SchemaDraft.v3,
'https://json-schema.org/draft-04/schema': SchemaDraft.v4,
'https://json-schema.org/draft-06/schema': SchemaDraft.v6,
'https://json-schema.org/draft-07/schema': SchemaDraft.v7,
'https://json-schema.org/draft/2019-09/schema': SchemaDraft.v2019_09,
'https://json-schema.org/draft/2020-12/schema': SchemaDraft.v2020_12
};
Expand Down Expand Up @@ -378,7 +401,7 @@ export class JSONDocument {
function getSchemaDraft(schema: JSONSchema, fallBack = SchemaDraft.v2020_12) {
let schemaId = schema.$schema;
if (schemaId) {
return schemaDraftFromId[schemaId] ?? fallBack;
return getSchemaDraftFromId(schemaId) ?? fallBack;
}
return fallBack;
}
Expand Down
5 changes: 2 additions & 3 deletions src/services/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ export const schemaContributions: ISchemaContributions = {
schemaAssociations: [],
schemas: {
// bundle the schema-schema to include (localized) descriptions
'http://json-schema.org/draft-04/schema#': {
'$schema': 'http://json-schema.org/draft-04/schema#',
'https://json-schema.org/draft-04/schema': {
'definitions': {
'schemaArray': {
'type': 'array',
Expand Down Expand Up @@ -294,7 +293,7 @@ export const schemaContributions: ISchemaContributions = {
},
'default': {}
},
'http://json-schema.org/draft-07/schema#': {
'https://json-schema.org/draft-07/schema': {
'definitions': {
'schemaArray': {
'type': 'array',
Expand Down
2 changes: 1 addition & 1 deletion src/services/jsonCompletion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ export class JSONCompletion {
private addDollarSchemaCompletions(separatorAfter: string, collector: CompletionsCollector): void {
const schemaIds = this.schemaService.getRegisteredSchemaIds(schema => schema === 'http' || schema === 'https');
schemaIds.forEach(schemaId => {
if (schemaId.startsWith('http://json-schema.org/draft-')) {
if (schemaId.startsWith('https://json-schema.org/draft-')) {
schemaId = schemaId + '#';
}
collector.add({
Expand Down
37 changes: 12 additions & 25 deletions src/services/jsonSchemaService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import * as Json from 'jsonc-parser';
import { JSONSchema, JSONSchemaMap, JSONSchemaRef } from '../jsonSchema';
import { URI } from 'vscode-uri';
import * as Strings from '../utils/strings';
import * as Parser from '../parser/jsonParser';
import { SchemaRequestService, WorkspaceContextService, PromiseConstructor, MatchingSchema, TextDocument, SchemaConfiguration } from '../jsonLanguageTypes';
import { asSchema, getSchemaDraftFromId, JSONDocument, normalizeId } from '../parser/jsonParser';
import { SchemaRequestService, WorkspaceContextService, PromiseConstructor, MatchingSchema, TextDocument, SchemaConfiguration, SchemaDraft } from '../jsonLanguageTypes';

import * as l10n from '@vscode/l10n';
import { createRegex } from '../utils/glob';
Expand All @@ -34,7 +34,7 @@ export interface IJSONSchemaService {
/**
* Looks up the appropriate schema for the given URI
*/
getSchemaForResource(resource: string, document?: Parser.JSONDocument): PromiseLike<ResolvedSchema | undefined>;
getSchemaForResource(resource: string, document?: JSONDocument): PromiseLike<ResolvedSchema | undefined>;

/**
* Returns all registered schema ids
Expand Down Expand Up @@ -193,9 +193,9 @@ export class ResolvedSchema {
public readonly schema: JSONSchema;
public readonly errors: string[];
public readonly warnings: string[];
public readonly schemaDraft: string | undefined;
public readonly schemaDraft: SchemaDraft | undefined;

constructor(schema: JSONSchema, errors: string[] = [], warnings: string[] = [], schemaDraft: string | undefined) {
constructor(schema: JSONSchema, errors: string[] = [], warnings: string[] = [], schemaDraft: SchemaDraft | undefined) {
this.schema = schema;
this.errors = errors;
this.warnings = warnings;
Expand All @@ -205,7 +205,7 @@ export class ResolvedSchema {
public getSection(path: string[]): JSONSchema | undefined {
const schemaRef = this.getSectionRecursive(path, this.schema);
if (schemaRef) {
return Parser.asSchema(schemaRef);
return asSchema(schemaRef);
}
return undefined;
}
Expand Down Expand Up @@ -390,9 +390,6 @@ export class JSONSchemaService implements IJSONSchemaService {
const errorMessage = l10n.t('Unable to load schema from \'{0}\'. No schema request service available', toDisplayString(url));
return this.promise.resolve(new UnresolvedSchema(<JSONSchema>{}, [errorMessage]));
}
if (url.startsWith('http://json-schema.org/')) {
url = 'https' + url.substring(4); // always access json-schema.org with https. See https://github.com/microsoft/vscode/issues/195189
}
return this.requestService(url).then(
content => {
if (!content) {
Expand Down Expand Up @@ -433,8 +430,8 @@ export class JSONSchemaService implements IJSONSchemaService {
const resolveErrors: string[] = schemaToResolve.errors.slice(0);
const schema = schemaToResolve.schema;

let schemaDraft = schema.$schema ? normalizeId(schema.$schema) : undefined;
if (schemaDraft === 'http://json-schema.org/draft-03/schema') {
const schemaDraft = schema.$schema ? getSchemaDraftFromId(schema.$schema) : undefined;
if (schemaDraft === SchemaDraft.v3) {
return this.promise.resolve(new ResolvedSchema({}, [l10n.t("Draft-03 schemas are not supported.")], [], schemaDraft));
}

Expand Down Expand Up @@ -634,7 +631,7 @@ export class JSONSchemaService implements IJSONSchemaService {
}
};

private getSchemaFromProperty(resource: string, document: Parser.JSONDocument): string | undefined {
private getSchemaFromProperty(resource: string, document: JSONDocument): string | undefined {
if (document.root?.type === 'object') {
for (const p of document.root.properties) {
if (p.keyNode.value === '$schema' && p.valueNode?.type === 'string') {
Expand Down Expand Up @@ -666,15 +663,15 @@ export class JSONSchemaService implements IJSONSchemaService {
return schemas;
}

public getSchemaURIsForResource(resource: string, document?: Parser.JSONDocument): string[] {
public getSchemaURIsForResource(resource: string, document?: JSONDocument): string[] {
let schemeId = document && this.getSchemaFromProperty(resource, document);
if (schemeId) {
return [schemeId];
}
return this.getAssociatedSchemas(resource);
}

public getSchemaForResource(resource: string, document?: Parser.JSONDocument): PromiseLike<ResolvedSchema | undefined> {
public getSchemaForResource(resource: string, document?: JSONDocument): PromiseLike<ResolvedSchema | undefined> {
if (document) {
// first use $schema if present
let schemeId = this.getSchemaFromProperty(resource, document);
Expand Down Expand Up @@ -704,7 +701,7 @@ export class JSONSchemaService implements IJSONSchemaService {
}
}

public getMatchingSchemas(document: TextDocument, jsonDocument: Parser.JSONDocument, schema?: JSONSchema): PromiseLike<MatchingSchema[]> {
public getMatchingSchemas(document: TextDocument, jsonDocument: JSONDocument, schema?: JSONSchema): PromiseLike<MatchingSchema[]> {
if (schema) {
const id = schema.id || ('schemaservice://untitled/matchingSchemas/' + idCounter++);
const handle = this.addSchemaHandle(id, schema);
Expand All @@ -724,16 +721,6 @@ export class JSONSchemaService implements IJSONSchemaService {

let idCounter = 0;

function normalizeId(id: string): string {
// remove trailing '#', normalize drive capitalization
try {
return URI.parse(id).toString(true);
} catch (e) {
return id;
}

}

function normalizeResourceForMatching(resource: string): string {
// remove queries and fragments, normalize drive capitalization
try {
Expand Down
4 changes: 2 additions & 2 deletions src/test/completion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1079,8 +1079,8 @@ suite('JSON Completion', () => {
await testCompletionsFor('{ "$schema": | }', schema, {
items: [
{ label: '"http://myschemastore/test1"', resultText: '{ "$schema": "http://myschemastore/test1" }' },
{ label: '"http://json-schema.org/draft-04/schema#"', resultText: '{ "$schema": "http://json-schema.org/draft-04/schema#" }' },
{ label: '"http://json-schema.org/draft-07/schema#"', resultText: '{ "$schema": "http://json-schema.org/draft-07/schema#" }' }
{ label: '"https://json-schema.org/draft-04/schema#"', resultText: '{ "$schema": "https://json-schema.org/draft-04/schema#" }' },
{ label: '"https://json-schema.org/draft-07/schema#"', resultText: '{ "$schema": "https://json-schema.org/draft-07/schema#" }' }
]
});
await testCompletionsFor('{ "$schema": "|', schema, {
Expand Down
2 changes: 1 addition & 1 deletion src/test/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1831,7 +1831,7 @@ suite('JSON Schema', () => {

test('schema resolving severity', async function () {
const schema: JSONSchema = {
$schema: 'http://json-schema.org/draft-03/schema',
$schema: 'http://json-schema.org/draft-03/schema#',
type: 'string'
};

Expand Down