@biomejs/runtime 0.0.0-stage → 0.0.1

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/package.json CHANGED
@@ -1,6 +1,42 @@
1
1
  {
2
2
  "name": "@biomejs/runtime",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.0.1",
4
+ "description": "JavaScript APIs for Biome JS plugins",
5
+ "scripts": {
6
+ "test:types": "tsc --project tsconfig.json"
7
+ },
8
+ "files": [
9
+ "README.md",
10
+ "LICENSE-APACHE",
11
+ "LICENSE-MIT",
12
+ "diagnostics.d.ts",
13
+ "plugin.d.ts",
14
+ "plugin.js",
15
+ "js_ast.d.ts",
16
+ "semantic.d.ts"
17
+ ],
18
+ "exports": {
19
+ "./plugin": {
20
+ "types": "./plugin.d.ts",
21
+ "default": "./plugin.js"
22
+ }
23
+ },
24
+ "license": "MIT OR Apache-2.0",
25
+ "homepage": "https://biomejs.dev",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/biomejs/biome.git",
29
+ "directory": "packages/@biomejs/runtime"
30
+ },
31
+ "author": "Biome Developers and Contributors",
32
+ "bugs": "https://github.com/biomejs/biome/issues",
33
+ "devDependencies": {
34
+ "typescript": "7.0.2"
35
+ },
36
+ "peerDependencies": {
37
+ "@biomejs/biome": "*"
38
+ },
39
+ "publishConfig": {
40
+ "provenance": true
41
+ }
42
+ }
package/plugin.d.ts ADDED
@@ -0,0 +1,317 @@
1
+ import type { Severity } from "./diagnostics";
2
+ import type {
3
+ AnyJsAstNode,
4
+ JsAstElement,
5
+ JsAstNode,
6
+ JsAstToken,
7
+ JsNodeByKind,
8
+ JsTokenKind,
9
+ } from "./js_ast";
10
+ import type { SemanticModel } from "./semantic";
11
+
12
+ export * from "./diagnostics";
13
+ export * from "./js_ast";
14
+ export * from "./semantic";
15
+
16
+ declare const queriedNode: unique symbol;
17
+ declare const nativeMutation: unique symbol;
18
+
19
+ /**
20
+ * A query matching AST nodes by their syntax kinds, created with {@link ast}.
21
+ *
22
+ * `N` is the union of the node types matched by the query; it only exists at
23
+ * the type level, to infer the argument type of {@link Rule#run}.
24
+ */
25
+ interface Query<N extends JsAstNode, K extends keyof ContextByQuery> {
26
+ readonly type: K;
27
+ readonly kinds: readonly (keyof JsNodeByKind)[];
28
+ readonly [queriedNode]?: N;
29
+ }
30
+
31
+ export type AstQuery<N extends JsAstNode> = Query<N, "ast">;
32
+ export type SemanticQuery<N extends JsAstNode> = Query<N, "semantic">;
33
+
34
+ /** File information supplied to each invocation of a rule. */
35
+ export interface RuleContext {
36
+ /** The analyzed file's path, as supplied by Biome. */
37
+ readonly filePath: string;
38
+ /** The parsing mode of the analyzed source, including embedded snippets. */
39
+ readonly sourceType: JsFileSource;
40
+ }
41
+
42
+ /** File information and semantic analysis supplied to a semantic rule. */
43
+ export interface SemanticRuleContext extends RuleContext {
44
+ /** Bindings and references in the original analyzed source. */
45
+ readonly model: SemanticModel;
46
+ }
47
+
48
+ type ContextByQuery = {
49
+ ast: RuleContext;
50
+ semantic: SemanticRuleContext;
51
+ };
52
+
53
+ /** JavaScript or TypeScript parsing settings for the analyzed source. */
54
+ export interface JsFileSource {
55
+ readonly language:
56
+ | { readonly kind: "javascript" }
57
+ | { readonly kind: "typescript"; readonly definitionFile: boolean };
58
+ /** Syntax extensions permitted in this source. */
59
+ readonly variant: "standard" | "standardRestricted" | "jsx";
60
+ readonly moduleKind: "module" | "script";
61
+ readonly version: "es2022" | "esNext";
62
+ readonly embeddingKind: JsEmbeddingKind;
63
+ }
64
+
65
+ /** The host framework and parsing mode of embedded JavaScript or TypeScript. */
66
+ export type JsEmbeddingKind =
67
+ | { readonly kind: "none" }
68
+ | {
69
+ readonly kind: "astro";
70
+ readonly frontmatter: boolean;
71
+ readonly isClassAttribute: boolean;
72
+ }
73
+ | {
74
+ readonly kind: "vue";
75
+ readonly setup: boolean;
76
+ readonly isSource: boolean;
77
+ readonly eventHandler: boolean;
78
+ }
79
+ | {
80
+ readonly kind: "svelte";
81
+ readonly fileKind: "component" | "sourceModule";
82
+ readonly embeddingKind:
83
+ | "source"
84
+ | "expression"
85
+ | "snippetSignature"
86
+ | "legacyConst"
87
+ | "declaration";
88
+ };
89
+
90
+ /**
91
+ * A lint rule, created with {@link defineRule} and exported from the plugin
92
+ * with `export const`. The name of the export is used as the rule name.
93
+ */
94
+ export interface Rule<
95
+ N extends JsAstNode,
96
+ K extends keyof ContextByQuery = "ast",
97
+ > {
98
+ /**
99
+ * The query selecting the nodes the rule runs on.
100
+ */
101
+ readonly query: Query<N, K>;
102
+
103
+ /**
104
+ * Called with every node matching the query.
105
+ * `context` information is read-only
106
+ *
107
+ * For example, inspect declarations only in TypeScript sources:
108
+ * ```ts
109
+ * export const myRule = defineRule({
110
+ * query: ast("JS_VARIABLE_STATEMENT"),
111
+ * run(node, context) {
112
+ * if (context.sourceType.language.kind !== "typescript") return;
113
+ * registerDiagnostic(node, "information", `Declaration in ${context.filePath}.`);
114
+ * },
115
+ * });
116
+ * ```
117
+ */
118
+ readonly run: (node: NoInfer<N>, context: NoInfer<ContextByQuery[K]>) => void;
119
+ }
120
+
121
+ /**
122
+ * Creates a query matching every node of the given syntax kinds.
123
+ */
124
+ export function ast<K extends readonly (keyof JsNodeByKind)[]>(
125
+ ...kinds: K
126
+ ): AstQuery<JsNodeByKind[K[number]]>;
127
+
128
+ /**
129
+ * Matches nodes by their syntax kinds and provides a semantic model in `context`.
130
+ *
131
+ * For example, inspect every read of a declared binding:
132
+ * ```ts
133
+ * export const inspectReads = defineRule({
134
+ * query: semantic("JS_IDENTIFIER_BINDING"),
135
+ * run(node, context) {
136
+ * const binding = context.model.asBinding(node);
137
+ * for (const reference of binding?.allReads() ?? []) {
138
+ * registerDiagnostic(reference.syntax(), "information", "Binding read here.");
139
+ * }
140
+ * },
141
+ * });
142
+ * ```
143
+ */
144
+ export function semantic<K extends readonly (keyof JsNodeByKind)[]>(
145
+ ...kinds: K
146
+ ): SemanticQuery<JsNodeByKind[K[number]]>;
147
+
148
+ /**
149
+ * Defines a lint rule. Export the returned rule with `export const` to
150
+ * register it to the analyzer.
151
+ */
152
+ export function defineRule<
153
+ N extends JsAstNode,
154
+ K extends keyof ContextByQuery = "ast",
155
+ >(rule: Rule<N, K>): Rule<N, K>;
156
+
157
+ /**
158
+ * Collects replacements and removals for one code fix without changing the
159
+ * source being analyzed. Create one with {@link createMutation}.
160
+ *
161
+ * Replacements can reuse existing nodes and tokens or use newly created ones.
162
+ * You are responsible for making sure the resulting code is valid. For example,
163
+ * removing an argument does not automatically remove its comma.
164
+ *
165
+ * Replacements preserve the original node or token's leading and trailing
166
+ * comments and whitespace. Removals delete them along with the node or token.
167
+ *
168
+ * Edits to the same node, or to a node, and its children can overwrite each
169
+ * other. Combine these changes into a single replacement for a predictable
170
+ * result.
171
+ *
172
+ * To attach the fix to a diagnostic, set {@link CodeFix.mutation} to this object
173
+ * and pass the fix to {@link registerDiagnostic}. Finish adding changes first:
174
+ * once registered, this mutation cannot be changed or attached to another
175
+ * diagnostic.
176
+ *
177
+ * You can keep nodes, tokens, and unfinished mutations between `run()` calls.
178
+ * Report a fix only for the same source the mutation was created from.
179
+ */
180
+ export interface JsMutation {
181
+ readonly [nativeMutation]: true;
182
+ /**
183
+ * Replaces a node, keeping its leading and trailing comments and whitespace.
184
+ * The replacement can be an existing node or one created by a field-update method.
185
+ *
186
+ * For example, change a numeric literal to `2`:
187
+ * ```ts
188
+ * const next = literal.withValueToken(factory.token("JS_NUMBER_LITERAL", "2"));
189
+ * mutation.replaceNode(literal, next);
190
+ * ```
191
+ */
192
+ replaceNode(previous: AnyJsAstNode, next: AnyJsAstNode): void;
193
+ /**
194
+ * Replaces a token, keeping its leading and trailing comments and whitespace.
195
+ * Pass token objects, not the strings returned by token fields.
196
+ *
197
+ * For example, change a declaration's keyword to `let`:
198
+ * ```ts
199
+ * const keyword = declaration.token("kindToken");
200
+ * if (keyword) {
201
+ * mutation.replaceToken(keyword, factory.token("LET_KW"));
202
+ * }
203
+ * ```
204
+ */
205
+ replaceToken(previous: JsAstToken, next: JsAstToken): void;
206
+ /**
207
+ * Replaces a node with a node, or a token with a token, keeping the original's
208
+ * leading and trailing comments and whitespace. Useful with childrenWithTokens().
209
+ *
210
+ * For example, replace a binary expression's operator with `===`:
211
+ * ```ts
212
+ * const operator = binary.childrenWithTokens()[1];
213
+ * if (operator) {
214
+ * mutation.replaceElement(operator, factory.token("EQ3"));
215
+ * }
216
+ * ```
217
+ */
218
+ replaceElement(previous: JsAstElement, next: JsAstElement): void;
219
+ /**
220
+ * Removes a node and its leading and trailing comments and whitespace.
221
+ * Adjacent commas and other separators are not removed automatically.
222
+ *
223
+ * For example, remove a debugger statement from a block:
224
+ * ```ts
225
+ * mutation.removeNode(debuggerStatement);
226
+ * ```
227
+ */
228
+ removeNode(node: AnyJsAstNode): void;
229
+ /**
230
+ * Removes a token and its leading and trailing comments and whitespace.
231
+ * Use token(field) to get the token object rather than its text.
232
+ *
233
+ * For example, remove a statement's optional semicolon:
234
+ * ```ts
235
+ * const semicolon = statement.token("semicolonToken");
236
+ * if (semicolon) mutation.removeToken(semicolon);
237
+ * ```
238
+ */
239
+ removeToken(token: JsAstToken): void;
240
+ /**
241
+ * Removes a node or token and its leading and trailing comments and whitespace.
242
+ * Useful when iterating over the result of childrenWithTokens().
243
+ *
244
+ * For example, remove the first argument and its following comma:
245
+ * ```ts
246
+ * const [argument, comma] = argumentList.childrenWithTokens();
247
+ * if (argument && comma?.kind === "COMMA") {
248
+ * mutation.removeElement(argument);
249
+ * mutation.removeElement(comma);
250
+ * }
251
+ * ```
252
+ */
253
+ removeElement(element: JsAstElement): void;
254
+ }
255
+
256
+ /**
257
+ * Starts collecting edits for the source containing `node`. You can pass any
258
+ * node from that source, not just the top-level node.
259
+ *
260
+ * Adding edits does not change the source or the nodes you already have. To
261
+ * execute the edits as a fix, pass the mutation to {@link registerDiagnostic}
262
+ * as part of a {@link CodeFix}.
263
+ *
264
+ * For example, prepare a fix that removes a statement:
265
+ * ```ts
266
+ * const mutation = createMutation(statement);
267
+ * mutation.removeNode(statement);
268
+ * ```
269
+ */
270
+ export function createMutation(node: AnyJsAstNode): JsMutation;
271
+
272
+ /** Helpers for creating replacement tokens. */
273
+ export const factory: {
274
+ /**
275
+ * Creates a token to use as a replacement in a code fix.
276
+ *
277
+ * `kind` names the token type. Keywords and punctuation have a fixed spelling,
278
+ * so `text` can be omitted or set to that spelling. For identifiers and literals,
279
+ * supply the desired text, including quotes when creating a string literal.
280
+ * The text is used as written, without adding spaces or comments.
281
+ *
282
+ * For example, create a keyword, an identifier, and a string literal:
283
+ * ```ts
284
+ * const keyword = factory.token("LET_KW");
285
+ * const name = factory.token("IDENT", "newName");
286
+ * const message = factory.token("JS_STRING_LITERAL", '"hello"');
287
+ * ```
288
+ */
289
+ readonly token: (kind: JsTokenKind, text?: string) => JsAstToken;
290
+ };
291
+
292
+ /** A suggested source edit attached to a diagnostic. */
293
+ export interface CodeFix {
294
+ readonly mutation: JsMutation;
295
+ /** A message describing the suggested edit. */
296
+ readonly message: string;
297
+ /** The kind of fix. */
298
+ readonly kind: "safe" | "unsafe";
299
+ }
300
+
301
+ /**
302
+ * Reports an issue found by a plugin rule. Biome highlights the code represented
303
+ * by `node` and displays `message` at the requested severity.
304
+ *
305
+ * Provide `fix` to include a suggested code change alongside the diagnostic.
306
+ *
307
+ * For example, report a warning on a variable declaration:
308
+ * ```ts
309
+ * registerDiagnostic(declaration, "warning", "Use let or const instead of var.");
310
+ * ```
311
+ */
312
+ export function registerDiagnostic(
313
+ node: JsAstNode,
314
+ severity: Severity,
315
+ message: string,
316
+ fix?: CodeFix,
317
+ ): void;
package/plugin.js ADDED
@@ -0,0 +1,3 @@
1
+ throw new Error(
2
+ "@biomejs/runtime/plugin is intended to be used in Biome JS plugins, did you mean `@biomejs/js-api`?",
3
+ );