Skip to content

feat: provide AST node types with internal types stripped out (alternative) #12968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/young-feet-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

feat: provide AST node types with internal types stripped out
2 changes: 1 addition & 1 deletion packages/svelte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
"@rollup/plugin-virtual": "^3.0.2",
"@types/aria-query": "^5.0.4",
"@types/node": "^20.11.5",
"dts-buddy": "^0.5.1",
"dts-buddy": "^0.5.3",
"esbuild": "^0.21.5",
"rollup": "^4.21.0",
"source-map": "^0.7.4",
Expand Down
4 changes: 4 additions & 0 deletions packages/svelte/scripts/generate-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ fs.writeFileSync(`${dir}/types/compiler/interfaces.d.ts`, "import '../index.js';

await createBundle({
output: `${dir}/types/index.d.ts`,
compilerOptions: {
// so that types/properties with `@internal` (and its dependencies) are removed from the output
stripInternal: true
},
modules: {
[pkg.name]: `${dir}/src/index.d.ts`,
[`${pkg.name}/action`]: `${dir}/src/action/public.d.ts`,
Expand Down
11 changes: 6 additions & 5 deletions packages/svelte/src/compiler/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/** @import { LegacyRoot } from './types/legacy-nodes.js' */
/** @import { CompileOptions, CompileResult, ValidatedCompileOptions, ModuleCompileOptions, Root } from '#compiler' */
/** @import { CompileOptions, CompileResult, ValidatedCompileOptions, ModuleCompileOptions } from '#compiler' */
/** @import { AST } from './public.js' */
import { walk as zimmerframe_walk } from 'zimmerframe';
import { convert } from './legacy.js';
import { parse as parse_acorn } from './phases/1-parse/acorn.js';
Expand Down Expand Up @@ -77,7 +78,7 @@ export function compileModule(source, options) {
* @overload
* @param {string} source
* @param {{ filename?: string; modern: true }} options
* @returns {Root}
* @returns {AST.Root}
*/

/**
Expand All @@ -90,7 +91,7 @@ export function compileModule(source, options) {
* @overload
* @param {string} source
* @param {{ filename?: string; modern?: false }} [options]
* @returns {LegacyRoot}
* @returns {Record<string, any>}
*/

/**
Expand All @@ -102,7 +103,7 @@ export function compileModule(source, options) {
* https://svelte.dev/docs/svelte-compiler#svelte-parse
* @param {string} source
* @param {{ filename?: string; rootDir?: string; modern?: boolean }} [options]
* @returns {Root | LegacyRoot}
* @returns {AST.Root | LegacyRoot}
*/
export function parse(source, { filename, rootDir, modern } = {}) {
state.reset_warning_filter(() => false);
Expand All @@ -114,7 +115,7 @@ export function parse(source, { filename, rootDir, modern } = {}) {

/**
* @param {string} source
* @param {Root} ast
* @param {AST.Root} ast
* @param {boolean | undefined} modern
*/
function to_public_ast(source, ast, modern) {
Expand Down
12 changes: 6 additions & 6 deletions packages/svelte/src/compiler/legacy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @import { Expression } from 'estree' */
/** @import { BaseNode, ConstTag, Root, SvelteNode, TemplateNode, Text } from '#compiler' */
/** @import { AST, SvelteNode, TemplateNode } from '#compiler' */
/** @import * as Legacy from './types/legacy-nodes.js' */
import { walk } from 'zimmerframe';
import {
Expand Down Expand Up @@ -36,7 +36,7 @@ function remove_surrounding_whitespace_nodes(nodes) {
/**
* Transform our nice modern AST into the monstrosity emitted by Svelte 4
* @param {string} source
* @param {Root} ast
* @param {AST.Root} ast
* @returns {Legacy.LegacyRoot}
*/
export function convert(source, ast) {
Expand Down Expand Up @@ -74,8 +74,8 @@ export function convert(source, ast) {
let end = null;

if (node.fragment.nodes.length > 0) {
const first = /** @type {BaseNode} */ (node.fragment.nodes.at(0));
const last = /** @type {BaseNode} */ (node.fragment.nodes.at(-1));
const first = /** @type {AST.BaseNode} */ (node.fragment.nodes.at(0));
const last = /** @type {AST.BaseNode} */ (node.fragment.nodes.at(-1));

start = first.start;
end = last.end;
Expand Down Expand Up @@ -242,7 +242,7 @@ export function convert(source, ast) {
return node;
}

const modern_node = /** @type {ConstTag} */ (node);
const modern_node = /** @type {AST.ConstTag} */ (node);
const { id: left } = { ...modern_node.declaration.declarations[0] };
// @ts-ignore
delete left.typeAnnotation;
Expand Down Expand Up @@ -584,7 +584,7 @@ export function convert(source, ast) {
const parent = path.at(-1);
if (parent?.type === 'RegularElement' && parent.name === 'style') {
// these text nodes are missing `raw` for some dumb reason
return /** @type {Text} */ ({
return /** @type {AST.Text} */ ({
type: 'Text',
start: node.start,
end: node.end,
Expand Down
20 changes: 10 additions & 10 deletions packages/svelte/src/compiler/migrate/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/** @import { Visitors } from 'zimmerframe' */
/** @import { ComponentAnalysis } from '../phases/types.js' */
/** @import { Scope } from '../phases/scope.js' */
/** @import * as Compiler from '#compiler' */
/** @import { AST, Binding, SvelteNode, ValidatedCompileOptions } from '#compiler' */
import MagicString from 'magic-string';
import { walk } from 'zimmerframe';
import { parse } from '../phases/1-parse/index.js';
Expand Down Expand Up @@ -30,7 +30,7 @@ export function migrate(source) {

const { customElement: customElementOptions, ...parsed_options } = parsed.options || {};

/** @type {Compiler.ValidatedCompileOptions} */
/** @type {ValidatedCompileOptions} */
const combined_options = {
...validate_component_options({}, ''),
...parsed_options,
Expand Down Expand Up @@ -160,7 +160,7 @@ export function migrate(source) {
let needs_reordering = false;

for (const [node, { dependencies }] of state.analysis.reactive_statements) {
/** @type {Compiler.Binding[]} */
/** @type {Binding[]} */
let ids = [];
if (
node.body.type === 'ExpressionStatement' &&
Expand Down Expand Up @@ -229,7 +229,7 @@ export function migrate(source) {
* }} State
*/

/** @type {Visitors<Compiler.SvelteNode, State>} */
/** @type {Visitors<SvelteNode, State>} */
const instance_script = {
_(node, { state, next }) {
// @ts-expect-error
Expand Down Expand Up @@ -335,7 +335,7 @@ const instance_script = {
// }
}

const binding = /** @type {Compiler.Binding} */ (state.scope.get(declarator.id.name));
const binding = /** @type {Binding} */ (state.scope.get(declarator.id.name));

if (state.analysis.uses_props && (declarator.init || binding.updated)) {
throw new Error(
Expand Down Expand Up @@ -478,7 +478,7 @@ const instance_script = {
}
};

/** @type {Visitors<Compiler.SvelteNode, State>} */
/** @type {Visitors<SvelteNode, State>} */
const template = {
Identifier(node, { state, path }) {
handle_identifier(node, state, path);
Expand Down Expand Up @@ -596,7 +596,7 @@ const template = {
/**
* @param {VariableDeclarator} declarator
* @param {MagicString} str
* @param {Array<Compiler.SvelteNode>} path
* @param {SvelteNode[]} path
*/
function extract_type_and_comment(declarator, str, path) {
const parent = path.at(-1);
Expand Down Expand Up @@ -641,11 +641,11 @@ function extract_type_and_comment(declarator, str, path) {
}

/**
* @param {Compiler.RegularElement | Compiler.SvelteElement | Compiler.SvelteWindow | Compiler.SvelteDocument | Compiler.SvelteBody} element
* @param {AST.RegularElement | AST.SvelteElement | AST.SvelteWindow | AST.SvelteDocument | AST.SvelteBody} element
* @param {State} state
*/
function handle_events(element, state) {
/** @type {Map<string, Compiler.OnDirective[]>} */
/** @type {Map<string, AST.OnDirective[]>} */
const handlers = new Map();
for (const attribute of element.attributes) {
if (attribute.type !== 'OnDirective') continue;
Expand Down Expand Up @@ -880,7 +880,7 @@ function get_node_range(source, node) {
}

/**
* @param {Compiler.OnDirective} last
* @param {AST.OnDirective} last
* @param {State} state
*/
function generate_event_name(last, state) {
Expand Down
10 changes: 5 additions & 5 deletions packages/svelte/src/compiler/phases/1-parse/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/** @import { TemplateNode, Fragment, Root, SvelteOptionsRaw } from '#compiler' */
/** @import { AST, TemplateNode } from '#compiler' */
// @ts-expect-error acorn type definitions are borked in the release we use
import { isIdentifierStart, isIdentifierChar } from 'acorn';
import fragment from './state/fragment.js';
Expand Down Expand Up @@ -31,10 +31,10 @@ export class Parser {
/** @type {TemplateNode[]} */
stack = [];

/** @type {Fragment[]} */
/** @type {AST.Fragment[]} */
fragments = [];

/** @type {Root} */
/** @type {AST.Root} */
root;

/** @type {Record<string, boolean>} */
Expand Down Expand Up @@ -122,7 +122,7 @@ export class Parser {
(thing) => thing.type === 'SvelteOptions'
);
if (options_index !== -1) {
const options = /** @type {SvelteOptionsRaw} */ (this.root.fragment.nodes[options_index]);
const options = /** @type {AST.SvelteOptionsRaw} */ (this.root.fragment.nodes[options_index]);
this.root.fragment.nodes.splice(options_index, 1);
this.root.options = read_options(options);

Expand Down Expand Up @@ -292,7 +292,7 @@ export class Parser {

/**
* @param {string} template
* @returns {Root}
* @returns {AST.Root}
*/
export function parse(template) {
const parser = new Parser(template);
Expand Down
10 changes: 5 additions & 5 deletions packages/svelte/src/compiler/phases/1-parse/read/options.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/** @import { ObjectExpression } from 'estree' */
/** @import { SvelteOptionsRaw, Root, SvelteOptions } from '#compiler' */
/** @import { AST } from '#compiler' */
import { NAMESPACE_MATHML, NAMESPACE_SVG } from '../../../../constants.js';
import * as e from '../../../errors.js';

const regex_valid_tag_name = /^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/;

/**
* @param {SvelteOptionsRaw} node
* @returns {Root['options']}
* @param {AST.SvelteOptionsRaw} node
* @returns {AST.Root['options']}
*/
export default function read_options(node) {
/** @type {SvelteOptions} */
/** @type {AST.SvelteOptions} */
const component_options = {
start: node.start,
end: node.end,
Expand Down Expand Up @@ -39,7 +39,7 @@ export default function read_options(node) {
break; // eslint doesn't know this is unnecessary
}
case 'customElement': {
/** @type {SvelteOptions['customElement']} */
/** @type {AST.SvelteOptions['customElement']} */
const ce = {};
const { value: v } = attribute;
const value = v === true || Array.isArray(v) ? v : [v];
Expand Down
8 changes: 4 additions & 4 deletions packages/svelte/src/compiler/phases/1-parse/read/script.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @import { Program } from 'estree' */
/** @import { Attribute, SpreadAttribute, Directive, Script } from '#compiler' */
/** @import { AST, Directive } from '#compiler' */
/** @import { Parser } from '../index.js' */
import * as acorn from '../acorn.js';
import { regex_not_newline_characters } from '../../patterns.js';
Expand All @@ -16,8 +16,8 @@ const ALLOWED_ATTRIBUTES = ['context', 'generics', 'lang', 'module'];
/**
* @param {Parser} parser
* @param {number} start
* @param {Array<Attribute | SpreadAttribute | Directive>} attributes
* @returns {Script}
* @param {Array<AST.Attribute | AST.SpreadAttribute | Directive>} attributes
* @returns {AST.Script}
*/
export function read_script(parser, start, attributes) {
const script_start = parser.index;
Expand Down Expand Up @@ -45,7 +45,7 @@ export function read_script(parser, start, attributes) {
/** @type {'default' | 'module'} */
let context = 'default';

for (const attribute of /** @type {Attribute[]} */ (attributes)) {
for (const attribute of /** @type {AST.Attribute[]} */ (attributes)) {
if (RESERVED_ATTRIBUTES.includes(attribute.name)) {
e.script_reserved_attribute(attribute, attribute.name);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/svelte/src/compiler/phases/1-parse/read/style.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/** @import { Attribute, SpreadAttribute, Directive, Css } from '#compiler' */
/** @import { AST, Css, Directive } from '#compiler' */
/** @import { Parser } from '../index.js' */
import * as e from '../../../errors.js';

Expand All @@ -18,7 +18,7 @@ const REGEX_HTML_COMMENT_CLOSE = /-->/;
/**
* @param {Parser} parser
* @param {number} start
* @param {Array<Attribute | SpreadAttribute | Directive>} attributes
* @param {Array<AST.Attribute | AST.SpreadAttribute | Directive>} attributes
* @returns {Css.StyleSheet}
*/
export default function read_style(parser, start, attributes) {
Expand Down
Loading