aontu 0.46.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aontu.js +5 -0
- package/dist/aontu.js.map +1 -1
- package/dist/err.js +1 -1
- package/dist/err.js.map +1 -1
- package/dist/hints.js +1 -0
- package/dist/hints.js.map +1 -1
- package/dist/lang.d.ts +1 -1
- package/dist/lang.js +45 -18
- package/dist/lang.js.map +1 -1
- package/dist/lsp-server.d.ts +14 -0
- package/dist/lsp-server.js +87 -0
- package/dist/lsp-server.js.map +1 -0
- package/dist/lsp.d.ts +71 -0
- package/dist/lsp.js +375 -0
- package/dist/lsp.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/type.d.ts +1 -1
- package/dist/unify.js +31 -4
- package/dist/unify.js.map +1 -1
- package/dist/utility.js +9 -2
- package/dist/utility.js.map +1 -1
- package/dist/val/BagVal.js +20 -2
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/DisjunctVal.js +25 -16
- package/dist/val/DisjunctVal.js.map +1 -1
- package/dist/val/IntegerVal.js +1 -0
- package/dist/val/IntegerVal.js.map +1 -1
- package/dist/val/LowerFuncVal.d.ts +1 -1
- package/dist/val/LowerFuncVal.js +1 -1
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.js +127 -16
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/NumberVal.js +7 -2
- package/dist/val/NumberVal.js.map +1 -1
- package/dist/val/OpBaseVal.d.ts +1 -1
- package/dist/val/OpBaseVal.js +1 -1
- package/dist/val/OpBaseVal.js.map +1 -1
- package/dist/val/ScalarVal.js +3 -1
- package/dist/val/ScalarVal.js.map +1 -1
- package/dist/val/Val.d.ts +2 -0
- package/dist/val/Val.js +16 -1
- package/dist/val/Val.js.map +1 -1
- package/dist/val/VarVal.js +5 -3
- package/dist/val/VarVal.js.map +1 -1
- package/package.json +22 -14
- package/src/aontu.ts +5 -0
- package/src/err.ts +1 -1
- package/src/hints.ts +2 -0
- package/src/lang.ts +46 -18
- package/src/lsp-server.ts +109 -0
- package/src/lsp.ts +486 -0
- package/src/type.ts +1 -1
- package/src/unify.ts +33 -4
- package/src/utility.ts +11 -2
- package/src/val/BagVal.ts +22 -2
- package/src/val/DisjunctVal.ts +27 -18
- package/src/val/IntegerVal.ts +1 -0
- package/src/val/LowerFuncVal.ts +1 -1
- package/src/val/MapVal.ts +138 -23
- package/src/val/NumberVal.ts +7 -2
- package/src/val/OpBaseVal.ts +1 -1
- package/src/val/ScalarVal.ts +3 -1
- package/src/val/Val.ts +18 -1
- package/src/val/VarVal.ts +6 -4
package/dist/val/VarVal.js
CHANGED
|
@@ -40,12 +40,14 @@ class VarVal extends FeatureVal_1.FeatureVal {
|
|
|
40
40
|
if (!(nameVal.isRef) && type_1.DONE === nameVal.dc) {
|
|
41
41
|
if (nameVal instanceof StringVal_1.StringVal) {
|
|
42
42
|
let found = ctx.vars[nameVal.peg];
|
|
43
|
+
// TODO: support complex values
|
|
44
|
+
const ft = typeof found;
|
|
45
|
+
// Single ladder: a missing var must report `unknown_var` and not
|
|
46
|
+
// fall through to the `invalid_var_kind` default below.
|
|
43
47
|
if (undefined === found) {
|
|
44
48
|
out = (0, err_1.makeNilErr)(ctx, 'unknown_var', this, peer);
|
|
45
49
|
}
|
|
46
|
-
|
|
47
|
-
const ft = typeof found;
|
|
48
|
-
if (null === found) {
|
|
50
|
+
else if (null === found) {
|
|
49
51
|
out = this.place(new NullVal_1.NullVal({ peg: null }));
|
|
50
52
|
}
|
|
51
53
|
else if ('string' === ft) {
|
package/dist/val/VarVal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VarVal.js","sourceRoot":"","sources":["../../src/val/VarVal.ts"],"names":[],"mappings":";AAAA,yDAAyD;;;AASzD,kCAEgB;AAEhB,gCAIe;AAQf,2CAAuC;AAEvC,6CAAyC;AACzC,uCAAmC;AACnC,6CAAyC;AACzC,2CAAuC;AACvC,6CAAyC;AAGzC,wCAImB;AAGnB,qDAAqD;AAErD,MAAM,MAAO,SAAQ,uBAAU;IAG7B,YACE,IAAa,EACb,GAAkB;QAElB,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QANlB,UAAK,GAAG,IAAI,CAAA;IAOZ,CAAC;IAGD,KAAK,CAAC,IAAS,EAAE,GAAiB;QAChC,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,IAAI,IAAA,qBAAW,EAAC,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;QAE1E,IAAI,GAAQ,CAAA;QAEZ,IAAI,OAAO,CAAA;QAEX,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACnB,qCAAqC;YACrC,oCAAoC;YACpC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;gBACnB,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAA;gBACxB,OAAO,GAAG,IAAI,CAAC,GAAG,CAAA;YACpB,CAAC;iBACI,CAAC;gBACJ,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAA,YAAE,EAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;YAClF,CAAC;QACH,CAAC;aACI,CAAC;YACJ,6BAA6B;YAC7B,OAAO,GAAG,IAAI,qBAAS,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAA;QACtD,CAAC;QAED,6DAA6D;QAC7D,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,WAAI,KAAK,OAAO,CAAC,EAAE,EAAE,CAAC;YAC5C,IAAI,OAAO,YAAY,qBAAS,EAAE,CAAC;gBACjC,IAAI,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"VarVal.js","sourceRoot":"","sources":["../../src/val/VarVal.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aontu",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.48.0",
|
|
4
4
|
"main": "dist/aontu.js",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"types": "dist/aontu.d.ts",
|
|
7
7
|
"bin": {
|
|
8
|
-
"aontu": "dist/cli.js"
|
|
8
|
+
"aontu": "dist/cli.js",
|
|
9
|
+
"aontu-lsp": "dist/lsp-server.js"
|
|
9
10
|
},
|
|
10
11
|
"description": "Unifier.",
|
|
11
12
|
"homepage": "https://github.com/rjrodger/aontu",
|
|
@@ -26,13 +27,19 @@
|
|
|
26
27
|
"clean": "rm -rf dist dist-test node_modules yarn.lock package-lock.json",
|
|
27
28
|
"reset": "npm run clean && npm i && npm run build && npm test",
|
|
28
29
|
"version": "node -r fs -e \"v=require('./package.json').version;s=fs.readFileSync('./aontu.ts').toString();if(!s.includes('VERSION = \\''+v+'\\'')){s=s.replace(/VERSION = '.*?'/,'VERSION = \\''+v+'\\'');fs.writeFileSync('./aontu.ts',s)}\"",
|
|
30
|
+
"repo-bump": "npm version patch --no-git-tag-version && node -e \"console.log('bumped to v' + require('./package.json').version + ' (package.json only - commit via repo-tag / repo-release)')\"",
|
|
29
31
|
"repo-tag": "REPO_VERSION=`node -e \"console.log(require('./package').version)\"` && echo TAG: v$REPO_VERSION && git commit -a -m v$REPO_VERSION && git push && git tag v$REPO_VERSION && git push --tags;",
|
|
32
|
+
"repo-tag-dry": "REPO_VERSION=`node -e \"console.log(require('./package').version)\"` && echo \"[dry-run] TAG: v$REPO_VERSION\" && if git rev-parse -q --verify refs/tags/v$REPO_VERSION >/dev/null; then echo \"[dry-run] WARNING: tag v$REPO_VERSION already exists - bump the version first\"; else echo \"[dry-run] would commit -a, push, tag v$REPO_VERSION and push --tags; nothing done\"; fi && git status --short",
|
|
30
33
|
"repo-publish": "npm run clean && npm i && npm run repo-publish-quick",
|
|
31
|
-
"repo-publish-
|
|
34
|
+
"repo-publish-dry": "npm run clean && npm i && npm run repo-publish-quick-dry",
|
|
35
|
+
"repo-publish-quick": "npm run build && npm run test && npm publish --registry https://registry.npmjs.org --access=public",
|
|
36
|
+
"repo-publish-quick-dry": "npm run build && npm run test && ( npm publish --dry-run --registry https://registry.npmjs.org --access=public || echo \"[dry-run] npm publish refused (see npm error above) - usually the version is already published; bump package.json before a real release\" )",
|
|
37
|
+
"repo-release": "npm run repo-publish && npm run repo-tag",
|
|
38
|
+
"repo-release-dry": "npm run repo-publish-quick-dry && npm run repo-tag-dry"
|
|
32
39
|
},
|
|
33
40
|
"license": "MIT",
|
|
34
41
|
"engines": {
|
|
35
|
-
"node": ">=
|
|
42
|
+
"node": ">=24"
|
|
36
43
|
},
|
|
37
44
|
"files": [
|
|
38
45
|
"src",
|
|
@@ -40,22 +47,23 @@
|
|
|
40
47
|
"LICENSE"
|
|
41
48
|
],
|
|
42
49
|
"dependencies": {
|
|
43
|
-
"@
|
|
44
|
-
"@
|
|
45
|
-
"@
|
|
46
|
-
"@jsonic
|
|
47
|
-
"
|
|
50
|
+
"@tabnas/debug": "0.2.0",
|
|
51
|
+
"@tabnas/directive": "0.2.0",
|
|
52
|
+
"@tabnas/expr": "0.2.0",
|
|
53
|
+
"@tabnas/jsonic": "0.2.0",
|
|
54
|
+
"@tabnas/multisource": "0.2.0",
|
|
55
|
+
"@tabnas/path": "0.2.0"
|
|
48
56
|
},
|
|
49
57
|
"devDependencies": {
|
|
50
|
-
"@types/node": "
|
|
51
|
-
"memfs": "4.
|
|
58
|
+
"@types/node": "26.1.0",
|
|
59
|
+
"memfs": "4.59.0",
|
|
52
60
|
"typescript": "6.0.3"
|
|
53
61
|
},
|
|
54
62
|
"aliasify": {
|
|
55
63
|
"aliases": {
|
|
56
|
-
"@
|
|
57
|
-
"@
|
|
58
|
-
"@
|
|
64
|
+
"@tabnas/multisource/resolver/file": "@tabnas/multisource/dist/resolver/file.js",
|
|
65
|
+
"@tabnas/multisource/resolver/pkg": "@tabnas/multisource/dist/resolver/pkg.js",
|
|
66
|
+
"@tabnas/multisource/resolver/mem": "@tabnas/multisource/dist/resolver/mem.js"
|
|
59
67
|
}
|
|
60
68
|
}
|
|
61
69
|
}
|
package/src/aontu.ts
CHANGED
|
@@ -35,6 +35,11 @@ class Aontu {
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
// Parse source into a matching Val AST, not yet unified.
|
|
38
|
+
//
|
|
39
|
+
// NOTE: the returned Val is SINGLE-USE — unify()/generate() refine the
|
|
40
|
+
// tree in place (see Val.unify), so do not unify or generate the same
|
|
41
|
+
// parsed Val more than once, and do not share it across threads. Call
|
|
42
|
+
// parse() again for a fresh tree.
|
|
38
43
|
parse(src: string, opts?: AontuOptions, ac?: AontuContext): Val | undefined {
|
|
39
44
|
let out: Val | undefined
|
|
40
45
|
let errs: any[] = []
|
package/src/err.ts
CHANGED
package/src/hints.ts
CHANGED
|
@@ -109,6 +109,8 @@ const hints: Record<string, string> = {
|
|
|
109
109
|
'|:empty': 'Empty disjunction. The disjunction has no valid alternatives.',
|
|
110
110
|
'|:empty-dist': 'Empty disjunction distribution. All alternatives in the disjunction are invalid.',
|
|
111
111
|
|
|
112
|
+
'max_depth': 'Input nesting is too deep to process safely.',
|
|
113
|
+
|
|
112
114
|
// Function errors (dynamic patterns)
|
|
113
115
|
'func': 'Function operation failed. See the specific function name for details.',
|
|
114
116
|
'make': 'Failed to create a new value. The make operation could not construct the value.',
|
package/src/lang.ts
CHANGED
|
@@ -5,42 +5,43 @@
|
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
Jsonic,
|
|
8
|
+
Tabnas,
|
|
8
9
|
Plugin,
|
|
9
10
|
Rule,
|
|
10
11
|
RuleSpec,
|
|
11
12
|
Context as JsonicContext,
|
|
12
13
|
JsonicError,
|
|
13
|
-
} from 'jsonic'
|
|
14
|
+
} from '@tabnas/jsonic'
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
import { Debug } from '
|
|
17
|
+
import { Debug } from '@tabnas/debug'
|
|
17
18
|
|
|
18
19
|
import {
|
|
19
20
|
MultiSource
|
|
20
|
-
} from '@
|
|
21
|
+
} from '@tabnas/multisource'
|
|
21
22
|
|
|
22
|
-
// TODO: @
|
|
23
|
+
// TODO: @tabnas/multisource should support virtual fs
|
|
23
24
|
|
|
24
25
|
import {
|
|
25
26
|
makeFileResolver
|
|
26
|
-
} from '@
|
|
27
|
+
} from '@tabnas/multisource/resolver/file'
|
|
27
28
|
|
|
28
29
|
import {
|
|
29
30
|
makePkgResolver
|
|
30
|
-
} from '@
|
|
31
|
+
} from '@tabnas/multisource/resolver/pkg'
|
|
31
32
|
|
|
32
33
|
import {
|
|
33
34
|
makeMemResolver
|
|
34
|
-
} from '@
|
|
35
|
+
} from '@tabnas/multisource/resolver/mem'
|
|
35
36
|
|
|
36
37
|
import {
|
|
37
38
|
Expr,
|
|
38
39
|
Op,
|
|
39
|
-
} from '@
|
|
40
|
+
} from '@tabnas/expr'
|
|
40
41
|
|
|
41
42
|
import {
|
|
42
43
|
Path
|
|
43
|
-
} from '@
|
|
44
|
+
} from '@tabnas/path'
|
|
44
45
|
|
|
45
46
|
import type {
|
|
46
47
|
Val,
|
|
@@ -93,9 +94,11 @@ import { OpenFuncVal } from './val/OpenFuncVal'
|
|
|
93
94
|
import { SuperFuncVal } from './val/SuperFuncVal'
|
|
94
95
|
|
|
95
96
|
|
|
97
|
+
const asPlugin = (p: unknown): Plugin => p as Plugin
|
|
98
|
+
|
|
96
99
|
let AontuJsonic: Plugin = function AontuLang(jsonic: Jsonic) {
|
|
97
100
|
|
|
98
|
-
jsonic.use(Path)
|
|
101
|
+
jsonic.use(asPlugin(Path))
|
|
99
102
|
|
|
100
103
|
// TODO: refactor Val constructor
|
|
101
104
|
// let addsite = (v: Val, p: string[]) => (v.path = [...(p || [])], v)
|
|
@@ -250,6 +253,8 @@ help isolate the syntax error.`,
|
|
|
250
253
|
'negative-prefix': (r: Rule, ctx: JsonicContext, _op: Op, terms: any) => {
|
|
251
254
|
let val = terms[0]
|
|
252
255
|
val.peg = -1 * val.peg
|
|
256
|
+
// Normalize -0 to 0 (keeps the AST and canon free of negative zero).
|
|
257
|
+
if (0 === val.peg) val.peg = 0
|
|
253
258
|
return addsite(val, r, ctx)
|
|
254
259
|
},
|
|
255
260
|
|
|
@@ -277,7 +282,7 @@ help isolate the syntax error.`,
|
|
|
277
282
|
|
|
278
283
|
|
|
279
284
|
jsonic
|
|
280
|
-
.use(Expr, {
|
|
285
|
+
.use(asPlugin(Expr), {
|
|
281
286
|
op: {
|
|
282
287
|
// disjunct < conjunct: c & b | a -> (c & b) | a
|
|
283
288
|
'conjunct': {
|
|
@@ -374,13 +379,23 @@ help isolate the syntax error.`,
|
|
|
374
379
|
|
|
375
380
|
rs
|
|
376
381
|
.open([
|
|
377
|
-
{
|
|
382
|
+
{
|
|
383
|
+
s: [CJ, CL], p: 'map', b: 2, n: { pk: 1 },
|
|
384
|
+
// @tabnas seeds a descended rule's node from its parent; without
|
|
385
|
+
// a fresh node here the nested spread map (`a:&:{x:1}`) would
|
|
386
|
+
// share the parent map's node object and self-reference.
|
|
387
|
+
a: (r: Rule) => { r.node = {} },
|
|
388
|
+
g: 'spread'
|
|
389
|
+
},
|
|
378
390
|
|
|
379
391
|
{
|
|
380
392
|
s: [OPTKEY, QM],
|
|
381
393
|
c: (r) => 0 == r.d,
|
|
382
394
|
p: 'map',
|
|
383
395
|
b: 2,
|
|
396
|
+
// Fresh node (see spread alt above): the optional dive descends
|
|
397
|
+
// to a map and must not share the parent's node object.
|
|
398
|
+
a: (r: Rule) => { r.node = {} },
|
|
384
399
|
g: 'pair,jsonic,top,aontu-optional',
|
|
385
400
|
},
|
|
386
401
|
|
|
@@ -389,12 +404,13 @@ help isolate the syntax error.`,
|
|
|
389
404
|
p: 'map',
|
|
390
405
|
b: 2,
|
|
391
406
|
n: { pk: 1 },
|
|
407
|
+
a: (r: Rule) => { r.node = {} },
|
|
392
408
|
g: 'pair,jsonic,top,dive,aontu-optional',
|
|
393
409
|
},
|
|
394
410
|
|
|
395
411
|
])
|
|
396
412
|
|
|
397
|
-
.
|
|
413
|
+
.ac((r: Rule, ctx: JsonicContext) => {
|
|
398
414
|
|
|
399
415
|
let valnode: Val = r.node
|
|
400
416
|
let valtype = typeof valnode
|
|
@@ -555,7 +571,7 @@ help isolate the syntax error.`,
|
|
|
555
571
|
}
|
|
556
572
|
])
|
|
557
573
|
|
|
558
|
-
// NOTE: manually adjust path - @
|
|
574
|
+
// NOTE: manually adjust path - @tabnas/path ignores as not pair:true
|
|
559
575
|
.ao((r) => {
|
|
560
576
|
if (0 < r.d && r.u.spread) {
|
|
561
577
|
r.child.k.path = [...r.k.path, '&']
|
|
@@ -640,6 +656,13 @@ help isolate the syntax error.`,
|
|
|
640
656
|
|
|
641
657
|
|
|
642
658
|
|
|
659
|
+
// SECURITY: the default resolver reads any file/package the process can
|
|
660
|
+
// reach — @"path" follows relative paths (`@"../../etc/passwd"`) and
|
|
661
|
+
// symlinks with no containment check, and @"pkg" can require() arbitrary
|
|
662
|
+
// installed modules. This is intentional for the CLI, but it means a
|
|
663
|
+
// `.aon` source can read referenced files; the LSP uses this same
|
|
664
|
+
// resolver, so treat opening an untrusted source as running it. Pass a
|
|
665
|
+
// confined `options.resolver` to restrict reads in less-trusted contexts.
|
|
643
666
|
function makeModelResolver(options: any) {
|
|
644
667
|
const useRequire = options.require || require
|
|
645
668
|
|
|
@@ -662,7 +685,7 @@ function makeModelResolver(options: any) {
|
|
|
662
685
|
popts: any,
|
|
663
686
|
rule: Rule,
|
|
664
687
|
ctx: JsonicContext,
|
|
665
|
-
jsonic:
|
|
688
|
+
jsonic: Tabnas
|
|
666
689
|
) {
|
|
667
690
|
|
|
668
691
|
let path = 'string' === typeof spec ? spec : spec?.peg
|
|
@@ -711,20 +734,25 @@ class Lang {
|
|
|
711
734
|
this.jsonic = Jsonic.make()
|
|
712
735
|
|
|
713
736
|
if (this.opts.debug) {
|
|
714
|
-
this.jsonic.use(Debug, {
|
|
737
|
+
this.jsonic.use(asPlugin(Debug), {
|
|
715
738
|
trace: this.opts.trace
|
|
716
739
|
})
|
|
717
740
|
}
|
|
718
741
|
|
|
719
742
|
this.jsonic
|
|
720
|
-
.use(
|
|
721
|
-
.use(MultiSource, {
|
|
743
|
+
.use(asPlugin(MultiSource), {
|
|
722
744
|
resolver: options?.resolver || modelResolver,
|
|
745
|
+
// `.aon` is the preferred Aontu source extension; `.aontu` also
|
|
746
|
+
// works. `.jsonic` is retired (no longer auto-resolved); the
|
|
747
|
+
// default `['jsonic','jsc','json','js']` is overridden here.
|
|
748
|
+
// (Upstream option name is the misspelled `implictExt`.)
|
|
749
|
+
implictExt: ['aon', 'aontu'],
|
|
723
750
|
processor: {
|
|
724
751
|
aontu: 'jsonic',
|
|
725
752
|
aon: 'jsonic',
|
|
726
753
|
}
|
|
727
754
|
})
|
|
755
|
+
.use(AontuJsonic)
|
|
728
756
|
}
|
|
729
757
|
|
|
730
758
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
3
|
+
|
|
4
|
+
// Aontu Language Server (stdio).
|
|
5
|
+
//
|
|
6
|
+
// aontu-lsp
|
|
7
|
+
//
|
|
8
|
+
// Speaks LSP over stdio (JSON-RPC with Content-Length framing) and
|
|
9
|
+
// publishes unification diagnostics as `.aontu` files are edited. This
|
|
10
|
+
// binary is intentionally thin: all protocol logic lives in the reusable
|
|
11
|
+
// library ./lsp (LspHandler + computeDiagnostics). See docs/lsp.md for
|
|
12
|
+
// editor configuration.
|
|
13
|
+
|
|
14
|
+
import { LspHandler, Message, OutMessage } from './lsp'
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
// A byte-level LSP framing codec: feed it incoming chunks, give it a
|
|
18
|
+
// handler, and it decodes Content-Length frames, dispatches them, and
|
|
19
|
+
// writes framed replies. Kept transport-injectable (write/onExit) so it
|
|
20
|
+
// can be unit-tested without real stdio.
|
|
21
|
+
class FrameCodec {
|
|
22
|
+
private buffer = Buffer.alloc(0)
|
|
23
|
+
|
|
24
|
+
constructor(
|
|
25
|
+
private handler: LspHandler,
|
|
26
|
+
private write: (chunk: Buffer) => void,
|
|
27
|
+
private onExit: (code: number) => void,
|
|
28
|
+
) { }
|
|
29
|
+
|
|
30
|
+
// Feed a chunk of incoming bytes; processes any complete frames.
|
|
31
|
+
push(chunk: Buffer) {
|
|
32
|
+
this.buffer = Buffer.concat([this.buffer, chunk])
|
|
33
|
+
this.drain()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Called when the input stream ends.
|
|
37
|
+
end() {
|
|
38
|
+
this.onExit(this.handler.exitCode)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private drain() {
|
|
42
|
+
for (; ;) {
|
|
43
|
+
const headerEnd = this.buffer.indexOf('\r\n\r\n')
|
|
44
|
+
if (headerEnd < 0) return
|
|
45
|
+
|
|
46
|
+
const header = this.buffer.subarray(0, headerEnd).toString('ascii')
|
|
47
|
+
const match = /Content-Length:\s*(\d+)/i.exec(header)
|
|
48
|
+
if (null == match) {
|
|
49
|
+
// Malformed header block: skip past it and continue.
|
|
50
|
+
this.buffer = this.buffer.subarray(headerEnd + 4)
|
|
51
|
+
continue
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const length = parseInt(match[1], 10)
|
|
55
|
+
const bodyStart = headerEnd + 4
|
|
56
|
+
if (this.buffer.length < bodyStart + length) return // need more bytes
|
|
57
|
+
|
|
58
|
+
const body = this.buffer.subarray(bodyStart, bodyStart + length).toString('utf8')
|
|
59
|
+
this.buffer = this.buffer.subarray(bodyStart + length)
|
|
60
|
+
|
|
61
|
+
let msg: Message
|
|
62
|
+
try {
|
|
63
|
+
msg = JSON.parse(body)
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
continue // ignore unparseable frame
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
for (const out of this.handler.handle(msg)) {
|
|
70
|
+
this.send(out)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (this.handler.shouldExit) {
|
|
74
|
+
this.onExit(this.handler.exitCode)
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private send(out: OutMessage) {
|
|
81
|
+
const body = Buffer.from(JSON.stringify(out), 'utf8')
|
|
82
|
+
this.write(Buffer.from('Content-Length: ' + body.length + '\r\n\r\n', 'ascii'))
|
|
83
|
+
this.write(body)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
function main() {
|
|
89
|
+
const handler = new LspHandler()
|
|
90
|
+
const codec = new FrameCodec(
|
|
91
|
+
handler,
|
|
92
|
+
(chunk) => process.stdout.write(chunk),
|
|
93
|
+
(code) => process.exit(code),
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
process.stdin.on('data', (chunk: Buffer) => codec.push(chunk))
|
|
97
|
+
process.stdin.on('end', () => codec.end())
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
// Only auto-run when invoked as a program, not when imported by tests.
|
|
102
|
+
if (require.main === module) {
|
|
103
|
+
main()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
FrameCodec,
|
|
109
|
+
}
|