Skip to content

Commit

Permalink
Support exclusiveMinimum/Maximum as number (for microsoft/vscode#29152)
Browse files Browse the repository at this point in the history
  • Loading branch information
aeschli committed Oct 12, 2017
1 parent b557919 commit 2e5dfe7
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 35 deletions.
5 changes: 3 additions & 2 deletions src/jsonSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

export interface JSONSchema {
id?: string;
$id?: string;
$schema?: string;
type?: string | string[];
title?: string;
Expand All @@ -28,8 +29,8 @@ export interface JSONSchema {
maxLength?: number;
minimum?: number;
maximum?: number;
exclusiveMinimum?: boolean;
exclusiveMaximum?: boolean;
exclusiveMinimum?: boolean | number;
exclusiveMaximum?: boolean | number;
multipleOf?: number;
required?: string[];
$ref?: string;
Expand Down
74 changes: 44 additions & 30 deletions src/parser/jsonParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,44 +478,58 @@ export class NumberASTNode extends ASTNode {
});
}
}

if (typeof schema.minimum === 'number') {
if (schema.exclusiveMinimum && val <= schema.minimum) {
validationResult.problems.push({
location: { start: this.start, end: this.end },
severity: ProblemSeverity.Warning,
message: localize('exclusiveMinimumWarning', 'Value is below the exclusive minimum of {0}.', schema.minimum)
});
function getExclusiveLimit(limit: number | undefined, exclusive: boolean | number | undefined) : number | undefined {
if (typeof exclusive === 'number') {
return exclusive;
}
if (!schema.exclusiveMinimum && val < schema.minimum) {
validationResult.problems.push({
location: { start: this.start, end: this.end },
severity: ProblemSeverity.Warning,
message: localize('minimumWarning', 'Value is below the minimum of {0}.', schema.minimum)
});
if (typeof exclusive === 'boolean' && exclusive) {
return limit;
}
return void 0;
}

if (typeof schema.maximum === 'number') {
if (schema.exclusiveMaximum && val >= schema.maximum) {
validationResult.problems.push({
location: { start: this.start, end: this.end },
severity: ProblemSeverity.Warning,
message: localize('exclusiveMaximumWarning', 'Value is above the exclusive maximum of {0}.', schema.maximum)
});
}
if (!schema.exclusiveMaximum && val > schema.maximum) {
validationResult.problems.push({
location: { start: this.start, end: this.end },
severity: ProblemSeverity.Warning,
message: localize('maximumWarning', 'Value is above the maximum of {0}.', schema.maximum)
});
function getLimit(limit: number | undefined, exclusive: boolean | number | undefined) : number | undefined {
if (typeof exclusive !== 'boolean' || !exclusive) {
return limit;
}
return void 0;
}
let exclusiveMinimum = getExclusiveLimit(schema.minimum, schema.exclusiveMinimum);
if (typeof exclusiveMinimum === 'number' && val <= exclusiveMinimum) {
validationResult.problems.push({
location: { start: this.start, end: this.end },
severity: ProblemSeverity.Warning,
message: localize('exclusiveMinimumWarning', 'Value is below the exclusive minimum of {0}.', exclusiveMinimum)
});
}
let exclusiveMaximum = getExclusiveLimit(schema.maximum, schema.exclusiveMaximum);
if (typeof exclusiveMaximum === 'number' && val >= schema.exclusiveMaximum) {
validationResult.problems.push({
location: { start: this.start, end: this.end },
severity: ProblemSeverity.Warning,
message: localize('exclusiveMaximumWarning', 'Value is above the exclusive maximum of {0}.', exclusiveMaximum)
});
}
let minimum = getLimit(schema.minimum, schema.exclusiveMinimum);
if (typeof minimum === 'number' && val < minimum) {
validationResult.problems.push({
location: { start: this.start, end: this.end },
severity: ProblemSeverity.Warning,
message: localize('minimumWarning', 'Value is below the minimum of {0}.', minimum)
});
}
let maximum = getLimit(schema.maximum, schema.exclusiveMaximum);
if (typeof maximum === 'number' && val > maximum) {
validationResult.problems.push({
location: { start: this.start, end: this.end },
severity: ProblemSeverity.Warning,
message: localize('maximumWarning', 'Value is above the maximum of {0}.', maximum)
});
}

}
}


export class StringASTNode extends ASTNode {
public isKey: boolean;
public value: string;
Expand Down Expand Up @@ -878,7 +892,7 @@ class SchemaCollector implements ISchemaCollector {
}

class NoOpSchemaCollector implements ISchemaCollector {
private constructor() {}
private constructor() { }
get schemas() { return []; }
add(schema: IApplicableSchema) { }
merge(other: ISchemaCollector) { }
Expand Down
54 changes: 51 additions & 3 deletions src/test/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -571,8 +571,8 @@ suite('JSON Parser', () => {
}
}
});

assert.strictEqual(semanticErrors.length, 1, 'below minimum');
assert.strictEqual(semanticErrors[0].message, 'Value is below the minimum of 200.');

semanticErrors = result.validate({
type: 'object',
Expand All @@ -583,8 +583,8 @@ suite('JSON Parser', () => {
}
}
});

assert.strictEqual(semanticErrors.length, 1, 'above maximum');
assert.strictEqual(semanticErrors[0].message, 'Value is above the maximum of 130.');

semanticErrors = result.validate({
type: 'object',
Expand All @@ -596,8 +596,32 @@ suite('JSON Parser', () => {
}
}
});
assert.strictEqual(semanticErrors.length, 1, 'at exclusive mininum');
assert.strictEqual(semanticErrors[0].message, 'Value is below the exclusive minimum of 134.5.');

semanticErrors = result.validate({
type: 'object',
properties: {
"one": {
type: 'number',
minimum: 134.5,
exclusiveMinimum: false
}
}
});
assert.strictEqual(semanticErrors.length, 0);

semanticErrors = result.validate({
type: 'object',
properties: {
"one": {
type: 'number',
exclusiveMinimum: 134.5
}
}
});
assert.strictEqual(semanticErrors.length, 1, 'at exclusive mininum');
assert.strictEqual(semanticErrors[0].message, 'Value is below the exclusive minimum of 134.5.');

semanticErrors = result.validate({
type: 'object',
Expand All @@ -609,8 +633,32 @@ suite('JSON Parser', () => {
}
}
});
assert.strictEqual(semanticErrors.length, 1, 'at exclusive mininum');
assert.strictEqual(semanticErrors[0].message, 'Value is above the exclusive maximum of 134.5.');

assert.strictEqual(semanticErrors.length, 1, 'at exclusive maximum');
semanticErrors = result.validate({
type: 'object',
properties: {
"one": {
type: 'number',
maximum: 134.5,
exclusiveMaximum: false
}
}
});
assert.strictEqual(semanticErrors.length, 0);

semanticErrors = result.validate({
type: 'object',
properties: {
"one": {
type: 'number',
exclusiveMaximum: 134.5
}
}
});
assert.strictEqual(semanticErrors.length, 1, 'at exclusive mininum');
assert.strictEqual(semanticErrors[0].message, 'Value is above the exclusive maximum of 134.5.');

semanticErrors = result.validate({
type: 'object',
Expand Down

0 comments on commit 2e5dfe7

Please sign in to comment.