Skip to content

[WIP] Experimental Slim AstNode API #59992

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

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
3 changes: 2 additions & 1 deletion scripts/build/options.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import os from "os";
const ci = ["1", "true"].includes(process.env.CI ?? "");

const parsed = minimist(process.argv.slice(2), {
boolean: ["dirty", "light", "colors", "lkg", "soft", "fix", "failed", "keepFailed", "force", "built", "ci", "bundle", "typecheck", "lint", "coverage"],
boolean: ["dirty", "light", "colors", "lkg", "soft", "fix", "failed", "keepFailed", "force", "built", "ci", "bundle", "typecheck", "lint", "coverage", "bail"],
string: ["browser", "tests", "break", "host", "reporter", "stackTraceLimit", "timeout", "shards", "shardId"],
alias: {
b: "browser",
Expand Down Expand Up @@ -66,6 +66,7 @@ export default options;
* @property {boolean} built
* @property {boolean} soft
* @property {boolean} fix
* @property {boolean} bail
* @property {string} browser
* @property {string} tests
* @property {boolean} skipSysTests
Expand Down
1 change: 1 addition & 0 deletions scripts/build/tests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export async function runConsoleTests(runJs, defaultReporter, runInParallel, opt
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
if (!runInParallel) {
args.push(mochaJs);
if (cmdLineOptions.bail) args.push("--bail");
args.push("-R", findUpFile("scripts/failed-tests.cjs"));
args.push("-O", '"reporter=' + reporter + (keepFailed ? ",keepFailed=true" : "") + '"');
if (tests) {
Expand Down
110 changes: 83 additions & 27 deletions scripts/dtsBundler.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -307,33 +307,61 @@ function symbolsConflict(s1, s2) {
*/
function verifyMatchingSymbols(decl, isInternal) {
ts.visitEachChild(decl, /** @type {(node: ts.Node) => ts.Node} */ function visit(node) {
if (ts.isIdentifier(node) && ts.isPartOfTypeNode(node)) {
if (ts.isQualifiedName(node.parent) && node !== node.parent.left) {
return node;
}
if (ts.isParameter(node.parent) && node === node.parent.name) {
return node;
if (ts.isIdentifier(node)) {
let meaning = ts.SymbolFlags.None;
if (ts.isPartOfTypeNode(node)) {
if (ts.isQualifiedName(node.parent) && node !== node.parent.left) {
return node;
}
if (ts.isParameter(node.parent) && node === node.parent.name) {
return node;
}
if (ts.isNamedTupleMember(node.parent) && node === node.parent.name) {
return node;
}
meaning = ts.SymbolFlags.Type;
}
if (ts.isNamedTupleMember(node.parent) && node === node.parent.name) {
return node;
else if (ts.isExpressionWithTypeArguments(node.parent) &&
ts.isHeritageClause(node.parent.parent) &&
ts.isClassLike(node.parent.parent.parent)) {
meaning = ts.SymbolFlags.Value;
}

const symbolOfNode = typeChecker.getSymbolAtLocation(node);
if (!symbolOfNode) {
fail(`No symbol for node at ${nodeToLocation(node)}`);
}
const symbolInScope = findInScope(symbolOfNode.name);
if (!symbolInScope) {
if (symbolOfNode.declarations?.every(d => isLocalDeclaration(d) && d.getSourceFile() === decl.getSourceFile()) && !isSelfReference(node, symbolOfNode)) {
// The symbol is a local that needs to be copied into the scope.
scopeStack[scopeStack.length - 1].locals.set(symbolOfNode.name, { symbol: symbolOfNode, writeTarget: isInternal ? WriteTarget.Internal : WriteTarget.Both });
if (meaning) {
const symbolOfNode = typeChecker.getSymbolAtLocation(node);
if (!symbolOfNode) {
fail(`No symbol for node at ${nodeToLocation(node)}`);
}
const symbolInScope = findInScope(symbolOfNode.name);
if (!symbolInScope) {
/** @type {ts.Declaration[]} */
const declarations = [];
if (meaning === ts.SymbolFlags.Type && symbolOfNode.declarations) {
declarations.push(...symbolOfNode.declarations);
}
else if (meaning === ts.SymbolFlags.Value && symbolOfNode.valueDeclaration) {
declarations.push(symbolOfNode.valueDeclaration);
}
if (declarations.every(d => isLocalDeclaration(d) && d.getSourceFile() === decl.getSourceFile()) && !isSelfReference(node, symbolOfNode)) {
// The symbol is a local that needs to be copied into the scope.
const locals = scopeStack[scopeStack.length - 1].locals;
if (!locals.has(symbolOfNode.name)) {
locals.set(symbolOfNode.name, { symbol: symbolOfNode, writeTarget: isInternal ? WriteTarget.Internal : WriteTarget.Both });
if (symbolOfNode.valueDeclaration) {
const statement = getDeclarationStatement(symbolOfNode.valueDeclaration);
if (statement) {
verifyMatchingSymbols(statement, isInternal);
}
}
}
}
// We didn't find the symbol in scope at all. Just allow it and we'll fail at test time.
return node;
}

if (symbolsConflict(symbolOfNode, symbolInScope)) {
fail(`Declaration at ${nodeToLocation(decl)}\n references ${symbolOfNode.name} at ${symbolOfNode.declarations && nodeToLocation(symbolOfNode.declarations[0])},\n but containing scope contains a symbol with the same name declared at ${symbolInScope.declarations && nodeToLocation(symbolInScope.declarations[0])}`);
}
// We didn't find the symbol in scope at all. Just allow it and we'll fail at test time.
return node;
}

if (symbolsConflict(symbolOfNode, symbolInScope)) {
fail(`Declaration at ${nodeToLocation(decl)}\n references ${symbolOfNode.name} at ${symbolOfNode.declarations && nodeToLocation(symbolOfNode.declarations[0])},\n but containing scope contains a symbol with the same name declared at ${symbolInScope.declarations && nodeToLocation(symbolInScope.declarations[0])}`);
}
}

Expand All @@ -345,9 +373,10 @@ function verifyMatchingSymbols(decl, isInternal) {
* @param {ts.Declaration} decl
*/
function isLocalDeclaration(decl) {
return ts.canHaveModifiers(decl)
&& !ts.getModifiers(decl)?.some(m => m.kind === ts.SyntaxKind.ExportKeyword)
&& !!getDeclarationStatement(decl);
const statement = getDeclarationStatement(decl);
return !!statement
&& ts.canHaveModifiers(statement)
&& !ts.getModifiers(statement)?.some(m => m.kind === ts.SyntaxKind.ExportKeyword);
}

/**
Expand Down Expand Up @@ -456,7 +485,34 @@ function emitAsNamespace(name, parent, moduleSymbol, needExportModifier) {
symbol.declarations?.forEach(decl => {
// We already checked that getDeclarationStatement(decl) works for each declaration.
const statement = getDeclarationStatement(decl);
writeNode(/** @type {ts.Statement} */ (statement), decl.getSourceFile(), writeTarget);
if (!statement) return;

if (writeTarget & WriteTarget.Public) {
if (!ts.isInternalDeclaration(statement)) {
const publicStatement = ts.visitEachChild(statement, node => {
// No @internal comments in the public API.
if (ts.isInternalDeclaration(node)) {
return undefined;
}
// TODO: remove after https://github.com/microsoft/TypeScript/pull/58187 is released
if (ts.canHaveModifiers(node)) {
for (const modifier of ts.getModifiers(node) ?? []) {
if (modifier.kind === ts.SyntaxKind.PrivateKeyword) {
removeAllComments(node);
break;
}
}
}
return removeDeclareConstExport(node, /*needExportModifier*/ false);
}, /*context*/ undefined);
writeNode(/** @type {ts.Statement} */ (publicStatement), decl.getSourceFile(), WriteTarget.Public);
}
}

if (writeTarget & WriteTarget.Internal) {
const updated = ts.visitEachChild(statement, node => removeDeclareConstExport(node, childrenNeedExportModifier), /*context*/ undefined);
writeNode(/** @type {ts.Statement} */ (updated), decl.getSourceFile(), WriteTarget.Internal);
}
});
});

Expand Down
12 changes: 12 additions & 0 deletions src/compiler/_namespaces/ts.ast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// /** @internal */
// export * from "../nodes.js";
/** @internal */
export * from "../ast.js";
/** @internal */
export * from "../factory/astNodeTests.js";
/** @internal */
export * from "../factory/astNodeFactory.js";
/** @internal */
export * from "../factory/astParenthesizerRules.js";
/** @internal */
export * from "../astForEachChild.js";
7 changes: 6 additions & 1 deletion src/compiler/_namespaces/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,28 @@ export * from "../semver.js";
export * from "../performanceCore.js";
export * from "../tracing.js";
export * from "../types.js";
export * from "../ast.js";
export * from "../sys.js";
export * from "../path.js";
export * from "../diagnosticInformationMap.generated.js";
export * from "../scanner.js";
export * from "../utilitiesPublic.js";
export * from "../utilities.js";
export * from "../factory/baseNodeFactory.js";
export * from "../factory/parenthesizerRules.js";
export * from "../factory/astParenthesizerRules.js";
export * from "../factory/nodeConverters.js";
export * from "../factory/nodeFactory.js";
export * from "../factory/astNodeFactory.js";
export * from "../factory/emitNode.js";
export * from "../factory/astNodeTests.js";
export * from "../factory/emitHelpers.js";
export * from "../factory/nodeTests.js";
export * from "../factory/nodeChildren.js";
export * from "../factory/utilities.js";
export * from "../factory/utilitiesPublic.js";
export * from "../parser.js";
export * from "../forEachChild.js";
export * from "../astForEachChild.js";
export * from "../commandLineParser.js";
export * from "../moduleNameResolver.js";
export * from "../binder.js";
Expand Down
Loading
Loading