toilscript 0.1.12 → 0.1.13

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.12/dist/toilscript.js",
4
- "toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.12/dist/cli.js",
3
+ "toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.13/dist/toilscript.js",
4
+ "toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.13/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.12";
1
+ var ASSEMBLYSCRIPT_VERSION = "0.1.13";
2
2
  var ASSEMBLYSCRIPT_IMPORTMAP = {
3
3
  "imports": {
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",
4
+ "toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.13/dist/toilscript.js",
5
+ "toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.13/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.12",
11
+ "version": "0.1.13",
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
@@ -5,21 +5,26 @@
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
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:
8
+ * injects into a `@data` class, and treats a class/method that is only ever used
9
+ * via a toil decorator (`@data`, `@rest`, `@service`, `@remote`, ...) as unused.
10
+ * This plugin runs only inside the editor's language service (VS Code, WebStorm,
11
+ * etc. - never `tsc`/compiler builds) and removes exactly those false positives:
11
12
  *
12
13
  * TS1206 "Decorators are not valid here."
13
14
  * TS1249 "A decorator can only decorate a method implementation, not an overload."
14
15
  * 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).
16
+ * `@data`-injected member and `<T>` is a `@data` class (a typo on any other
17
+ * type still surfaces).
18
+ * TS6133 / TS6196 "'<x>' is declared but never used." - but ONLY when `<x>` is a
19
+ * class/method/function carrying a toil-native decorator (so the compiler
20
+ * uses it); an undecorated unused declaration is still greyed out.
17
21
  *
18
22
  * Every other diagnostic - unknown types, bad calls, missing names - passes
19
23
  * through untouched, so real type errors are still surfaced.
20
24
  */
21
25
  const DECORATOR_GRAMMAR_CODES = new Set([1206, 1249]);
22
26
  const PROPERTY_NOT_EXIST = 2339;
27
+ const DECLARED_NEVER_USED = new Set([6133, 6196]);
23
28
 
24
29
  /** Members the compiler injects into every `@data` class (instance + static). */
25
30
  const DATA_MEMBERS = new Set([
@@ -32,6 +37,32 @@ const DATA_MEMBERS = new Set([
32
37
  'dataId',
33
38
  ]);
34
39
 
40
+ /** Toil-native decorators whose presence means the compiler uses the declaration. */
41
+ const TOIL_DECORATORS = new Set([
42
+ 'data',
43
+ 'remote',
44
+ 'service',
45
+ 'rest',
46
+ 'route',
47
+ 'get',
48
+ 'post',
49
+ 'put',
50
+ 'del',
51
+ 'patch',
52
+ 'head',
53
+ 'options',
54
+ 'main',
55
+ 'global',
56
+ 'inline',
57
+ 'external',
58
+ 'unmanaged',
59
+ 'final',
60
+ 'operator',
61
+ 'lazy',
62
+ 'unsafe',
63
+ 'builtin',
64
+ ]);
65
+
35
66
  function init(modules) {
36
67
  const ts = modules.typescript;
37
68
 
@@ -46,21 +77,24 @@ function init(modules) {
46
77
  return found;
47
78
  }
48
79
 
49
- /** Whether a class declaration carries the `@data` decorator (bare or called). */
50
- function hasDataDecorator(decl) {
80
+ /** A decorator's bare name, for `@name` and `@name(...)`. */
81
+ function decoratorName(d) {
82
+ const e = d.expression;
83
+ return e && (e.text || (e.expression && e.expression.text));
84
+ }
85
+
86
+ function declHasDecorator(decl, names) {
51
87
  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;
88
+ return decorators.some((d) => {
89
+ const n = decoratorName(d);
90
+ return typeof names === 'string' ? n === names : !!n && names.has(n);
91
+ });
58
92
  }
59
93
 
60
94
  function declsAreDataClass(declarations) {
61
95
  return (
62
96
  !!declarations &&
63
- declarations.some((d) => ts.isClassDeclaration(d) && hasDataDecorator(d))
97
+ declarations.some((d) => ts.isClassDeclaration(d) && declHasDecorator(d, 'data'))
64
98
  );
65
99
  }
66
100
 
@@ -74,6 +108,18 @@ function init(modules) {
74
108
  return !!sym && declsAreDataClass(sym.declarations);
75
109
  }
76
110
 
111
+ function canHoldDecorators(node) {
112
+ return (
113
+ ts.isClassDeclaration(node) ||
114
+ ts.isClassExpression(node) ||
115
+ ts.isMethodDeclaration(node) ||
116
+ ts.isFunctionDeclaration(node) ||
117
+ ts.isPropertyDeclaration(node) ||
118
+ ts.isGetAccessorDeclaration(node) ||
119
+ ts.isSetAccessorDeclaration(node)
120
+ );
121
+ }
122
+
77
123
  return {
78
124
  create(info) {
79
125
  const ls = info.languageService;
@@ -85,6 +131,7 @@ function init(modules) {
85
131
  proxy[key] = typeof value === 'function' ? value.bind(ls) : value;
86
132
  }
87
133
 
134
+ // A TS2339 for a `@data`-injected member accessed on a `@data` class.
88
135
  const isInjectedDataMember = (fileName, diag) => {
89
136
  if (diag.code !== PROPERTY_NOT_EXIST || diag.start == null) return false;
90
137
  const program = ls.getProgram();
@@ -101,9 +148,24 @@ function init(modules) {
101
148
  return resolvesToDataClass(access.expression, program.getTypeChecker());
102
149
  };
103
150
 
151
+ // A "declared but never used" for a class/method/function with a toil decorator.
152
+ const isToilDecoratedUnused = (fileName, diag) => {
153
+ if (!DECLARED_NEVER_USED.has(diag.code) || diag.start == null) return false;
154
+ const program = ls.getProgram();
155
+ const sf = program && program.getSourceFile(fileName);
156
+ if (!sf) return false;
157
+ const node = nodeAt(sf, diag.start);
158
+ if (!node) return false;
159
+ const decl = canHoldDecorators(node) ? node : node.parent;
160
+ return !!decl && canHoldDecorators(decl) && declHasDecorator(decl, TOIL_DECORATORS);
161
+ };
162
+
104
163
  const strip = (fileName, diagnostics) =>
105
164
  diagnostics.filter(
106
- (d) => !DECORATOR_GRAMMAR_CODES.has(d.code) && !isInjectedDataMember(fileName, d),
165
+ (d) =>
166
+ !DECORATOR_GRAMMAR_CODES.has(d.code) &&
167
+ !isInjectedDataMember(fileName, d) &&
168
+ !isToilDecoratedUnused(fileName, d),
107
169
  );
108
170
 
109
171
  proxy.getSemanticDiagnostics = (fileName) =>
@@ -111,6 +173,12 @@ function init(modules) {
111
173
  proxy.getSyntacticDiagnostics = (fileName) =>
112
174
  strip(fileName, ls.getSyntacticDiagnostics(fileName));
113
175
 
176
+ // The "unused" greying is a suggestion diagnostic when `noUnusedLocals` is off.
177
+ if (typeof ls.getSuggestionDiagnostics === 'function') {
178
+ proxy.getSuggestionDiagnostics = (fileName) =>
179
+ ls.getSuggestionDiagnostics(fileName).filter((d) => !isToilDecoratedUnused(fileName, d));
180
+ }
181
+
114
182
  return proxy;
115
183
  },
116
184
  };