toilscript 0.1.11 → 0.1.12

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "imports": {
3
- "toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.11/dist/toilscript.js",
4
- "toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.11/dist/cli.js",
3
+ "toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.12/dist/toilscript.js",
4
+ "toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.12/dist/cli.js",
5
5
  "binaryen": "https://cdn.jsdelivr.net/npm/binaryen@129.0.0-nightly.20260428/index.js",
6
6
  "long": "https://cdn.jsdelivr.net/npm/long@5.3.2/index.js"
7
7
  }
package/dist/web.js CHANGED
@@ -1,8 +1,8 @@
1
- var ASSEMBLYSCRIPT_VERSION = "0.1.11";
1
+ var ASSEMBLYSCRIPT_VERSION = "0.1.12";
2
2
  var ASSEMBLYSCRIPT_IMPORTMAP = {
3
3
  "imports": {
4
- "toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.11/dist/toilscript.js",
5
- "toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.11/dist/cli.js",
4
+ "toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.12/dist/toilscript.js",
5
+ "toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.12/dist/cli.js",
6
6
  "binaryen": "https://cdn.jsdelivr.net/npm/binaryen@129.0.0-nightly.20260428/index.js",
7
7
  "long": "https://cdn.jsdelivr.net/npm/long@5.3.2/index.js"
8
8
  }
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "toilscript",
9
9
  "wasm"
10
10
  ],
11
- "version": "0.1.11",
11
+ "version": "0.1.12",
12
12
  "author": "Daniel Wirtz <dcode+assemblyscript@dcode.io>",
13
13
  "license": "Apache-2.0",
14
14
  "homepage": "https://github.com/dacely-cloud/toilscript",
package/std/ts-plugin.cjs CHANGED
@@ -4,19 +4,76 @@
4
4
  * Stock TypeScript has no grammar for toil-native decorators applied to
5
5
  * top-level functions and globals (`@main`, `@inline`, `@unmanaged`, ...), so
6
6
  * the editor's language service flags them as errors even though the toilscript
7
- * compiler (asc) handles them correctly. This plugin runs only inside the
8
- * editor's language service (VS Code, WebStorm, etc. never `tsc`/asc builds)
9
- * and removes exactly those decorator-grammar false positives:
7
+ * compiler handles them correctly. It also can't see the members the compiler
8
+ * injects into a `@data` class (`encode`/`decode`/`toJSON`/...). This plugin runs
9
+ * only inside the editor's language service (VS Code, WebStorm, etc. - never
10
+ * `tsc`/compiler builds) and removes exactly those false positives:
10
11
  *
11
12
  * TS1206 "Decorators are not valid here."
12
13
  * TS1249 "A decorator can only decorate a method implementation, not an overload."
14
+ * TS2339 "Property '<m>' does not exist on type '<T>'." - but ONLY when `<m>` is a
15
+ * `@data`-injected member and `<T>` is a `@data` class (so a typo on any
16
+ * other type still surfaces).
13
17
  *
14
- * Every other diagnostic unknown types, bad calls, missing names passes
18
+ * Every other diagnostic - unknown types, bad calls, missing names - passes
15
19
  * through untouched, so real type errors are still surfaced.
16
20
  */
17
21
  const DECORATOR_GRAMMAR_CODES = new Set([1206, 1249]);
22
+ const PROPERTY_NOT_EXIST = 2339;
23
+
24
+ /** Members the compiler injects into every `@data` class (instance + static). */
25
+ const DATA_MEMBERS = new Set([
26
+ 'encode',
27
+ 'encodeInto',
28
+ 'decode',
29
+ 'decodeFrom',
30
+ 'toJSON',
31
+ 'fromJSON',
32
+ 'dataId',
33
+ ]);
34
+
35
+ function init(modules) {
36
+ const ts = modules.typescript;
37
+
38
+ /** Deepest node spanning `pos`. */
39
+ function nodeAt(node, pos) {
40
+ if (pos < node.getStart() || pos >= node.getEnd()) return undefined;
41
+ let found = node;
42
+ node.forEachChild((child) => {
43
+ const inner = nodeAt(child, pos);
44
+ if (inner) found = inner;
45
+ });
46
+ return found;
47
+ }
48
+
49
+ /** Whether a class declaration carries the `@data` decorator (bare or called). */
50
+ function hasDataDecorator(decl) {
51
+ const decorators = (ts.getDecorators ? ts.getDecorators(decl) : decl.decorators) || [];
52
+ for (const d of decorators) {
53
+ const e = d.expression;
54
+ const name = e && (e.text || (e.expression && e.expression.text));
55
+ if (name === 'data') return true;
56
+ }
57
+ return false;
58
+ }
59
+
60
+ function declsAreDataClass(declarations) {
61
+ return (
62
+ !!declarations &&
63
+ declarations.some((d) => ts.isClassDeclaration(d) && hasDataDecorator(d))
64
+ );
65
+ }
66
+
67
+ /** Whether `expr` is (an instance of, or the static side of) a `@data` class. */
68
+ function resolvesToDataClass(expr, checker) {
69
+ const type = checker.getTypeAtLocation(expr);
70
+ const typeSym = type && type.getSymbol && type.getSymbol();
71
+ if (typeSym && declsAreDataClass(typeSym.declarations)) return true;
72
+ // Static access like `Player.decode(...)`: resolve the identifier's own symbol.
73
+ const sym = checker.getSymbolAtLocation(expr);
74
+ return !!sym && declsAreDataClass(sym.declarations);
75
+ }
18
76
 
19
- function init() {
20
77
  return {
21
78
  create(info) {
22
79
  const ls = info.languageService;
@@ -28,13 +85,31 @@ function init() {
28
85
  proxy[key] = typeof value === 'function' ? value.bind(ls) : value;
29
86
  }
30
87
 
31
- const strip = (diagnostics) =>
32
- diagnostics.filter((d) => !DECORATOR_GRAMMAR_CODES.has(d.code));
88
+ const isInjectedDataMember = (fileName, diag) => {
89
+ if (diag.code !== PROPERTY_NOT_EXIST || diag.start == null) return false;
90
+ const program = ls.getProgram();
91
+ const sf = program && program.getSourceFile(fileName);
92
+ if (!sf) return false;
93
+ const node = nodeAt(sf, diag.start);
94
+ const access =
95
+ node && ts.isPropertyAccessExpression(node)
96
+ ? node
97
+ : node && ts.isPropertyAccessExpression(node.parent)
98
+ ? node.parent
99
+ : undefined;
100
+ if (!access || !DATA_MEMBERS.has(access.name.text)) return false;
101
+ return resolvesToDataClass(access.expression, program.getTypeChecker());
102
+ };
103
+
104
+ const strip = (fileName, diagnostics) =>
105
+ diagnostics.filter(
106
+ (d) => !DECORATOR_GRAMMAR_CODES.has(d.code) && !isInjectedDataMember(fileName, d),
107
+ );
33
108
 
34
109
  proxy.getSemanticDiagnostics = (fileName) =>
35
- strip(ls.getSemanticDiagnostics(fileName));
110
+ strip(fileName, ls.getSemanticDiagnostics(fileName));
36
111
  proxy.getSyntacticDiagnostics = (fileName) =>
37
- strip(ls.getSyntacticDiagnostics(fileName));
112
+ strip(fileName, ls.getSyntacticDiagnostics(fileName));
38
113
 
39
114
  return proxy;
40
115
  },