diff --git a/__snapshots__/packages/core/test-out/service/Operations.spec.js b/__snapshots__/packages/core/test-out/service/Operations.spec.js deleted file mode 100644 index d11d3fe69..000000000 --- a/__snapshots__/packages/core/test-out/service/Operations.spec.js +++ /dev/null @@ -1,53 +0,0 @@ -exports['Operations Should add operations to parent correctly 1'] = { - "foo": 1, - "bar": 2, - "baz": 3 -} - -exports['Operations Should add operations to parent correctly 2'] = { - "foo": 42, - "bar": 2, - "baz": 3 -} - -exports['Operations Should add operations to parent correctly 3'] = { - "foo": 69, - "bar": 10, - "baz": 3 -} - -exports['Operations Should add operations to parent correctly 4'] = { - "foo": 1, - "bar": 2, - "baz": 3 -} - -exports['Operations Should add operations to parent correctly 5'] = { - "foo": 69, - "bar": 10, - "baz": 3 -} - -exports['Operations Should redo and undo correctly 1'] = { - "foo": 1, - "bar": 2, - "baz": 3 -} - -exports['Operations Should redo and undo correctly 2'] = { - "foo": 42, - "bar": 91, - "baz": 3 -} - -exports['Operations Should redo and undo correctly 3'] = { - "foo": 1, - "bar": 2, - "baz": 3 -} - -exports['Operations Should redo and undo correctly 4'] = { - "foo": 42, - "bar": 91, - "baz": 3 -} diff --git a/__snapshots__/packages/core/test-out/service/StateProxy.spec.js b/__snapshots__/packages/core/test-out/service/StateProxy.spec.js deleted file mode 100644 index 090fd8734..000000000 --- a/__snapshots__/packages/core/test-out/service/StateProxy.spec.js +++ /dev/null @@ -1,231 +0,0 @@ -exports['StateProxy Should branch off correctly 1'] = { - "symbols": { - "advancement": { - "foo": { - "category": "advancement" - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "symbol" - } - ] - } -} - -exports['StateProxy Should branch off correctly 2'] = { - "symbols": { - "advancement": { - "foo": { - "category": "advancement" - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "modified_symbol" - } - ] - } -} - -exports['StateProxy Should branch off correctly 3'] = { - "symbols": { - "advancement": { - "foo": { - "category": "not_advancement" - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "modified_symbol" - } - ] - } -} - -exports['StateProxy Should branch off correctly 4'] = { - "symbols": { - "advancement": { - "foo": { - "category": "advancement" - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "modified_symbol" - } - ] - } -} - -exports['StateProxy Should branch off correctly 5'] = { - "symbols": { - "advancement": { - "foo": { - "category": "not_not_advancement" - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "modified_symbol" - } - ] - } -} - -exports['StateProxy Should branch off correctly 6'] = { - "symbols": { - "advancement": { - "foo": { - "category": "advancement" - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "symbol" - } - ] - } -} - -exports['StateProxy Should branch off correctly 7'] = { - "symbols": { - "advancement": { - "foo": { - "category": "not_not_advancement" - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "modified_symbol" - } - ] - } -} - -exports['StateProxy Should create enumerable proxy 1'] = { - "symbols": { - "advancement": { - "foo": { - "category": "advancement" - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "symbol" - } - ] - } -} - -exports['StateProxy Should undo and redo changes correctly 1'] = { - "symbols": { - "advancement": { - "foo": { - "category": "advancement" - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "symbol" - } - ] - } -} - -exports['StateProxy Should undo and redo changes correctly 2'] = { - "symbols": { - "advancement": { - "foo": { - "category": "advancement" - }, - "bar": { - "category": "advancement", - "data": 42 - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "modified_symbol", - "symbol": { - "category": "advancement", - "data": 42 - } - } - ] - } -} - -exports['StateProxy Should undo and redo changes correctly 3'] = { - "symbols": { - "advancement": { - "foo": { - "category": "advancement" - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "symbol" - } - ] - } -} - -exports['StateProxy Should undo and redo changes correctly 4'] = { - "symbols": { - "advancement": { - "foo": { - "category": "advancement" - }, - "bar": { - "category": "advancement", - "data": 42 - } - } - }, - "node": { - "type": "file", - "children": [ - { - "type": "modified_symbol", - "symbol": { - "category": "advancement", - "data": 42 - } - } - ] - } -} diff --git a/__snapshots__/packages/json/test-out/parser/array.spec.js b/__snapshots__/packages/json/test-out/parser/array.spec.js index cc79d0fb6..815698a3b 100644 --- a/__snapshots__/packages/json/test-out/parser/array.spec.js +++ b/__snapshots__/packages/json/test-out/parser/array.spec.js @@ -488,20 +488,54 @@ exports['JSON array parser array() Parse "[1,2,]" 1'] = { "children": [ { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + } + ], + "value": { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + }, "range": { "start": 1, "end": 2 - }, - "value": 1 + } } ], "value": { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + } + ], + "value": { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + }, "range": { "start": 1, "end": 2 - }, - "value": 1 + } }, "sep": { "start": 2, @@ -517,20 +551,54 @@ exports['JSON array parser array() Parse "[1,2,]" 1'] = { "children": [ { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 3, + "end": 4 + }, + "value": "2" + } + ], + "value": { + "type": "long", + "range": { + "start": 3, + "end": 4 + }, + "value": "2" + }, "range": { "start": 3, "end": 4 - }, - "value": 2 + } } ], "value": { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 3, + "end": 4 + }, + "value": "2" + } + ], + "value": { + "type": "long", + "range": { + "start": 3, + "end": 4 + }, + "value": "2" + }, "range": { "start": 3, "end": 4 - }, - "value": 2 + } }, "sep": { "start": 4, @@ -568,20 +636,54 @@ exports['JSON array parser array() Parse "[1,2]" 1'] = { "children": [ { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + } + ], + "value": { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + }, "range": { "start": 1, "end": 2 - }, - "value": 1 + } } ], "value": { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + } + ], + "value": { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + }, "range": { "start": 1, "end": 2 - }, - "value": 1 + } }, "sep": { "start": 2, @@ -597,20 +699,54 @@ exports['JSON array parser array() Parse "[1,2]" 1'] = { "children": [ { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 3, + "end": 4 + }, + "value": "2" + } + ], + "value": { + "type": "long", + "range": { + "start": 3, + "end": 4 + }, + "value": "2" + }, "range": { "start": 3, "end": 4 - }, - "value": 2 + } } ], "value": { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 3, + "end": 4 + }, + "value": "2" + } + ], + "value": { + "type": "long", + "range": { + "start": 3, + "end": 4 + }, + "value": "2" + }, "range": { "start": 3, "end": 4 - }, - "value": 2 + } } } ] @@ -635,20 +771,54 @@ exports['JSON array parser array() Parse "[1]" 1'] = { "children": [ { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + } + ], + "value": { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + }, "range": { "start": 1, "end": 2 - }, - "value": 1 + } } ], "value": { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + } + ], + "value": { + "type": "long", + "range": { + "start": 1, + "end": 2 + }, + "value": "1" + }, "range": { "start": 1, "end": 2 - }, - "value": 1 + } } } ] @@ -687,20 +857,54 @@ exports['JSON array parser array() Parse "[[1],2]" 1'] = { "children": [ { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 2, + "end": 3 + }, + "value": "1" + } + ], + "value": { + "type": "long", + "range": { + "start": 2, + "end": 3 + }, + "value": "1" + }, "range": { "start": 2, "end": 3 - }, - "value": 1 + } } ], "value": { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 2, + "end": 3 + }, + "value": "1" + } + ], + "value": { + "type": "long", + "range": { + "start": 2, + "end": 3 + }, + "value": "1" + }, "range": { "start": 2, "end": 3 - }, - "value": 1 + } } } ] @@ -722,20 +926,54 @@ exports['JSON array parser array() Parse "[[1],2]" 1'] = { "children": [ { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 2, + "end": 3 + }, + "value": "1" + } + ], + "value": { + "type": "long", + "range": { + "start": 2, + "end": 3 + }, + "value": "1" + }, "range": { "start": 2, "end": 3 - }, - "value": 1 + } } ], "value": { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 2, + "end": 3 + }, + "value": "1" + } + ], + "value": { + "type": "long", + "range": { + "start": 2, + "end": 3 + }, + "value": "1" + }, "range": { "start": 2, "end": 3 - }, - "value": 1 + } } } ] @@ -754,20 +992,54 @@ exports['JSON array parser array() Parse "[[1],2]" 1'] = { "children": [ { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 5, + "end": 6 + }, + "value": "2" + } + ], + "value": { + "type": "long", + "range": { + "start": 5, + "end": 6 + }, + "value": "2" + }, "range": { "start": 5, "end": 6 - }, - "value": 2 + } } ], "value": { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 5, + "end": 6 + }, + "value": "2" + } + ], + "value": { + "type": "long", + "range": { + "start": 5, + "end": 6 + }, + "value": "2" + }, "range": { "start": 5, "end": 6 - }, - "value": 2 + } } } ] diff --git a/__snapshots__/packages/json/test-out/parser/number.spec.js b/__snapshots__/packages/json/test-out/parser/number.spec.js new file mode 100644 index 000000000..0502bf573 --- /dev/null +++ b/__snapshots__/packages/json/test-out/parser/number.spec.js @@ -0,0 +1,298 @@ +exports['JSON number parser number() Parse "+1" 1'] = { + "node": { + "type": "json:number", + "children": [ + { + "type": "float", + "range": { + "start": 0, + "end": 2 + }, + "value": 1 + } + ], + "value": { + "type": "float", + "range": { + "start": 0, + "end": 2 + }, + "value": 1 + }, + "range": { + "start": 0, + "end": 2 + } + }, + "errors": [ + { + "range": { + "start": 0, + "end": 2 + }, + "message": "Illegal float numeral that doesn't follow /^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][-+]?\\d+)?$/", + "severity": 3 + } + ] +} + +exports['JSON number parser number() Parse "-1" 1'] = { + "node": { + "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 0, + "end": 2 + }, + "value": "-1" + } + ], + "value": { + "type": "long", + "range": { + "start": 0, + "end": 2 + }, + "value": "-1" + }, + "range": { + "start": 0, + "end": 2 + } + }, + "errors": [] +} + +exports['JSON number parser number() Parse "0" 1'] = { + "node": { + "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 0, + "end": 1 + }, + "value": "0" + } + ], + "value": { + "type": "long", + "range": { + "start": 0, + "end": 1 + }, + "value": "0" + }, + "range": { + "start": 0, + "end": 1 + } + }, + "errors": [] +} + +exports['JSON number parser number() Parse "0.0" 1'] = { + "node": { + "type": "json:number", + "children": [ + { + "type": "float", + "range": { + "start": 0, + "end": 3 + }, + "value": 0 + } + ], + "value": { + "type": "float", + "range": { + "start": 0, + "end": 3 + }, + "value": 0 + }, + "range": { + "start": 0, + "end": 3 + } + }, + "errors": [] +} + +exports['JSON number parser number() Parse "1" 1'] = { + "node": { + "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 0, + "end": 1 + }, + "value": "1" + } + ], + "value": { + "type": "long", + "range": { + "start": 0, + "end": 1 + }, + "value": "1" + }, + "range": { + "start": 0, + "end": 1 + } + }, + "errors": [] +} + +exports['JSON number parser number() Parse "1.0" 1'] = { + "node": { + "type": "json:number", + "children": [ + { + "type": "float", + "range": { + "start": 0, + "end": 3 + }, + "value": 1 + } + ], + "value": { + "type": "float", + "range": { + "start": 0, + "end": 3 + }, + "value": 1 + }, + "range": { + "start": 0, + "end": 3 + } + }, + "errors": [] +} + +exports['JSON number parser number() Parse "1.0232E2" 1'] = { + "node": { + "type": "json:number", + "children": [ + { + "type": "float", + "range": { + "start": 0, + "end": 8 + }, + "value": 102.32 + } + ], + "value": { + "type": "float", + "range": { + "start": 0, + "end": 8 + }, + "value": 102.32 + }, + "range": { + "start": 0, + "end": 8 + } + }, + "errors": [] +} + +exports['JSON number parser number() Parse "1.2" 1'] = { + "node": { + "type": "json:number", + "children": [ + { + "type": "float", + "range": { + "start": 0, + "end": 3 + }, + "value": 1.2 + } + ], + "value": { + "type": "float", + "range": { + "start": 0, + "end": 3 + }, + "value": 1.2 + }, + "range": { + "start": 0, + "end": 3 + } + }, + "errors": [] +} + +exports['JSON number parser number() Parse "1.342E-10" 1'] = { + "node": { + "type": "json:number", + "children": [ + { + "type": "float", + "range": { + "start": 0, + "end": 9 + }, + "value": 1.342e-10 + } + ], + "value": { + "type": "float", + "range": { + "start": 0, + "end": 9 + }, + "value": 1.342e-10 + }, + "range": { + "start": 0, + "end": 9 + } + }, + "errors": [] +} + +exports['JSON number parser number() Parse "1E12" 1'] = { + "node": { + "type": "json:number", + "children": [ + { + "type": "float", + "range": { + "start": 0, + "end": 4 + }, + "value": 1000000000000 + } + ], + "value": { + "type": "float", + "range": { + "start": 0, + "end": 4 + }, + "value": 1000000000000 + }, + "range": { + "start": 0, + "end": 4 + } + }, + "errors": [] +} diff --git a/__snapshots__/packages/json/test-out/parser/object.spec.js b/__snapshots__/packages/json/test-out/parser/object.spec.js index 18c75db6c..996841447 100644 --- a/__snapshots__/packages/json/test-out/parser/object.spec.js +++ b/__snapshots__/packages/json/test-out/parser/object.spec.js @@ -1203,11 +1203,28 @@ exports['JSON object parser object() Parse "{1: 2}" 1'] = { "children": [ { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 4, + "end": 5 + }, + "value": "2" + } + ], + "value": { + "type": "long", + "range": { + "start": 4, + "end": 5 + }, + "value": "2" + }, "range": { "start": 4, "end": 5 - }, - "value": 2 + } } ], "sep": { @@ -1216,11 +1233,28 @@ exports['JSON object parser object() Parse "{1: 2}" 1'] = { }, "value": { "type": "json:number", + "children": [ + { + "type": "long", + "range": { + "start": 4, + "end": 5 + }, + "value": "2" + } + ], + "value": { + "type": "long", + "range": { + "start": 4, + "end": 5 + }, + "value": "2" + }, "range": { "start": 4, "end": 5 - }, - "value": 2 + } } } ] diff --git a/packages/json/src/formatter/index.ts b/packages/json/src/formatter/index.ts index c431ec981..60211dcd4 100644 --- a/packages/json/src/formatter/index.ts +++ b/packages/json/src/formatter/index.ts @@ -37,6 +37,9 @@ const object: Formatter = (node, ctx) => { return `{\n${fields.join(',\n')}\n${ctx.indent()}}` } +const number: Formatter = (node, ctx) => + ctx.meta.getFormatter(node.value.type)(node.value, ctx) + export function register(meta: MetaRegistry): void { meta.registerFormatter('json:array', array) meta.registerFormatter( @@ -44,7 +47,7 @@ export function register(meta: MetaRegistry): void { core.formatter.boolean, ) meta.registerFormatter('json:null', () => 'null') - meta.registerFormatter('json:number', core.formatter.float) + meta.registerFormatter('json:number', number) meta.registerFormatter('json:object', object) meta.registerFormatter('json:string', core.formatter.string) } diff --git a/packages/json/src/node/JsonAstNode.ts b/packages/json/src/node/JsonAstNode.ts index 0ba3df749..edea766a4 100644 --- a/packages/json/src/node/JsonAstNode.ts +++ b/packages/json/src/node/JsonAstNode.ts @@ -156,9 +156,10 @@ export namespace JsonStringNode { export interface JsonNumberExpectation extends JsonBaseExpectation { readonly type: 'json:number' } -export interface JsonNumberNode extends core.FloatBaseNode, JsonBaseAstNode { +export interface JsonNumberNode extends JsonBaseAstNode, core.AstNode { readonly type: 'json:number' - readonly value: number + readonly children: [core.LongNode | core.FloatNode] + readonly value: core.LongNode | core.FloatNode } export namespace JsonNumberNode { /* istanbul ignore next */ diff --git a/packages/json/src/parser/array.ts b/packages/json/src/parser/array.ts index c0546741b..da33d6b0d 100644 --- a/packages/json/src/parser/array.ts +++ b/packages/json/src/parser/array.ts @@ -2,15 +2,14 @@ import * as core from '@spyglassmc/core' import type { JsonArrayNode } from '../node/index.js' import { entry } from './entry.js' -export const array: core.Parser = (src, ctx) => { - const parser = core.list({ - start: '[', - value: entry, - sep: ',', - trailingSep: false, - end: ']', - }) - const ans = parser(src, ctx) as core.Mutable - ans.type = 'json:array' - return ans -} +export const array: core.Parser = (ctx, src) => + core.setType( + 'json:array', + core.list({ + start: '[', + value: entry, + sep: ',', + trailingSep: false, + end: ']', + }), + )(ctx, src) diff --git a/packages/json/src/parser/boolean.ts b/packages/json/src/parser/boolean.ts index 99daa8d14..9f6d10329 100644 --- a/packages/json/src/parser/boolean.ts +++ b/packages/json/src/parser/boolean.ts @@ -2,7 +2,7 @@ import * as core from '@spyglassmc/core' import { Range } from '@spyglassmc/core' import type { JsonBooleanNode } from '../node/index.js' -export const boolean: core.Parser = (src, ctx) => { +export const boolean: core.Parser = (src, _ctx) => { const start = src.cursor if (src.trySkip('false')) { return { diff --git a/packages/json/src/parser/number.ts b/packages/json/src/parser/number.ts index bd1c10eb7..e0d6f7a07 100644 --- a/packages/json/src/parser/number.ts +++ b/packages/json/src/parser/number.ts @@ -2,11 +2,25 @@ import * as core from '@spyglassmc/core' import type { JsonNumberNode } from '../node/index.js' export const number: core.Parser = (src, ctx) => { - const parser = core.float({ - // Regex form of the chart from https://www.json.org. - pattern: /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][-+]?\d+)?$/, - }) - const ans = parser(src, ctx) as core.Mutable - ans.type = 'json:number' - return ans as JsonNumberNode + const value = core.select([ + { + regex: /^-?(?:0|[1-9]\d*)(?!\d|[.eE])/, + parser: core.long({ + pattern: /^-?(?:0|[1-9]\d*)$/, + }), + }, + { + parser: core.float({ + // Regex form of the chart from https://www.json.org. + pattern: /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][-+]?\d+)?$/, + }), + }, + ])(src, ctx) + + return { + type: 'json:number', + children: [value], + value: value, + range: value.range, + } } diff --git a/packages/json/src/parser/object.ts b/packages/json/src/parser/object.ts index 58e058fe2..46a0cc190 100644 --- a/packages/json/src/parser/object.ts +++ b/packages/json/src/parser/object.ts @@ -3,8 +3,8 @@ import type { JsonObjectNode } from '../node/index.js' import { entry } from './entry.js' import { string } from './string.js' -export const object: core.InfallibleParser = (src, ctx) => { - return core.setType( +export const object: core.InfallibleParser = (src, ctx) => + core.setType( 'json:object', core.record({ start: '{', @@ -18,4 +18,3 @@ export const object: core.InfallibleParser = (src, ctx) => { end: '}', }), )(src, ctx) -} diff --git a/packages/json/src/parser/string.ts b/packages/json/src/parser/string.ts index 07e288437..ee054cd01 100644 --- a/packages/json/src/parser/string.ts +++ b/packages/json/src/parser/string.ts @@ -9,11 +9,8 @@ export const JsonStringOptions: core.StringOptions = { quotes: ['"'], } -export const string: core.Parser = (src, ctx) => { - const parser = core.string(JsonStringOptions) - const ans = parser(src, ctx) as core.Mutable< - JsonStringNode | core.StringNode - > - ans.type = 'json:string' - return ans as JsonStringNode -} +export const string: core.Parser = (src, ctx) => + core.setType( + 'json:string', + core.string(JsonStringOptions), + )(src, ctx) diff --git a/packages/json/test/parser/number.spec.ts b/packages/json/test/parser/number.spec.ts new file mode 100644 index 000000000..25979da38 --- /dev/null +++ b/packages/json/test/parser/number.spec.ts @@ -0,0 +1,28 @@ +import { + showWhitespaceGlyph, + testParser, +} from '@spyglassmc/core/test-out/utils.js' +import snapshot from 'snap-shot-it' +import { number } from '../../lib/parser/number.js' + +describe('JSON number parser', () => { + describe('number()', () => { + const cases: { content: string }[] = [ + { content: '1' }, + { content: '1.2' }, + { content: '1.0' }, + { content: '0.0' }, + { content: '0' }, + { content: '-1' }, + { content: '+1' }, + { content: '1E12' }, + { content: '1.0232E2' }, + { content: '1.342E-10' }, + ] + for (const { content } of cases) { + it(`Parse "${showWhitespaceGlyph(content)}"`, () => { + snapshot(testParser(number, content)) + }) + } + }) +})