Skip to content

Commit

Permalink
feat: provide AST node types with internal types stripped out (altern…
Browse files Browse the repository at this point in the history
…ative) (#12968)

Uses new dts-buddy capabilities and the corresponding tsconfig option to strip away types/properties (and their dependencies) that are marked with `@internal`

Also hides the legacy AST types from the output

To not clutter the exports, the AST types are moved into a namespace named AST

closes #12292
  • Loading branch information
dummdidumm authored Sep 1, 2024
1 parent b70d12c commit 2d03dc5
Show file tree
Hide file tree
Showing 133 changed files with 1,273 additions and 1,753 deletions.
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

0 comments on commit 2d03dc5

Please sign in to comment.