From 06d7f044bba60fc9aebd24f1c0d80fd21de7284a Mon Sep 17 00:00:00 2001 From: Zwe Zeya <79783783+ZweZeya@users.noreply.github.com> Date: Sat, 27 Apr 2024 14:51:28 +0800 Subject: [PATCH] 1401 add support for local module importexport to source typed (#1686) * add typechecking for export statement in typeErrorChecker * merge * update estree and TypedES * Fix broken submodule changes * Fix format --------- Co-authored-by: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Co-authored-by: Martin Henz --- package.json | 2 +- src/modules/preprocessor/index.ts | 1 + .../transformers/removeExports.ts | 2 +- .../transformProgramToFunctionDeclaration.ts | 7 ++++-- src/typeChecker/tsESTree.ts | 25 ++++++++++++++++--- src/typeChecker/typeErrorChecker.ts | 2 ++ src/types.ts | 6 ++++- src/utils/ast/astCreator.ts | 2 +- yarn.lock | 8 +++--- 9 files changed, 41 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index b772a6f6b..f8b2bf886 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@commander-js/extra-typings": "^12.0.1", "@joeychenofficial/alt-ergo-modified": "^2.4.0", "@ts-morph/bootstrap": "^0.18.0", - "@types/estree": "0.0.52", + "@types/estree": "^1.0.5", "acorn": "^8.8.2", "acorn-class-fields": "^1.0.0", "acorn-loose": "^8.0.0", diff --git a/src/modules/preprocessor/index.ts b/src/modules/preprocessor/index.ts index 76e3fb181..b81b1e716 100644 --- a/src/modules/preprocessor/index.ts +++ b/src/modules/preprocessor/index.ts @@ -1,4 +1,5 @@ import type es from 'estree' +// import * as TypedES from '../../typeChecker/tsESTree' import type { Context, IOptions } from '../..' import type { RecursivePartial } from '../../types' diff --git a/src/modules/preprocessor/transformers/removeExports.ts b/src/modules/preprocessor/transformers/removeExports.ts index d81ce907d..9699d9be0 100644 --- a/src/modules/preprocessor/transformers/removeExports.ts +++ b/src/modules/preprocessor/transformers/removeExports.ts @@ -21,7 +21,7 @@ export default function removeExports(program: es.Program): void { // it with the declaration node in its parent node's body. return node.declaration.type === 'FunctionDeclaration' || node.declaration.type === 'ClassDeclaration' - ? node.declaration + ? (node.declaration as es.FunctionDeclaration) : undefined case 'ExportNamedDeclaration': // If the ExportNamedDeclaration node contains a declaration, replace diff --git a/src/modules/preprocessor/transformers/transformProgramToFunctionDeclaration.ts b/src/modules/preprocessor/transformers/transformProgramToFunctionDeclaration.ts index 2d12015d1..b2b27622c 100644 --- a/src/modules/preprocessor/transformers/transformProgramToFunctionDeclaration.ts +++ b/src/modules/preprocessor/transformers/transformProgramToFunctionDeclaration.ts @@ -142,7 +142,11 @@ const getDefaultExportExpression = ( nodes: es.ModuleDeclaration[], exportedNameToIdentifierMap: Partial> ): es.Expression | null => { - let defaultExport: es.Expression | null = null + let defaultExport: + | es.MaybeNamedFunctionDeclaration + | es.MaybeNamedClassDeclaration + | es.Expression + | null = null // Handle default exports which are parsed as ExportNamedDeclaration AST nodes. // 'export { name as default };' is equivalent to 'export default name;' but @@ -164,7 +168,6 @@ const getDefaultExportExpression = ( // This should never occur because multiple default exports should have // been caught by the Acorn parser when parsing into an AST. assert(defaultExport === null, 'Encountered multiple default exports!') - if (isDeclaration(node.declaration)) { const identifier = getIdentifier(node.declaration) if (identifier === null) { diff --git a/src/typeChecker/tsESTree.ts b/src/typeChecker/tsESTree.ts index 6b1fa8dd9..0445894b4 100644 --- a/src/typeChecker/tsESTree.ts +++ b/src/typeChecker/tsESTree.ts @@ -6,7 +6,7 @@ interface BaseNodeWithoutComments { // The type property should be a string literal. For example, Identifier // has: `type: "Identifier"` type: string - loc?: es.SourceLocation | null | undefined + loc?: SourceLocation | null | undefined range?: [number, number] | undefined } @@ -49,6 +49,12 @@ export interface Comment extends BaseNodeWithoutComments { value: string } +export interface SourceLocation { + source?: string | null | undefined + start: Position + end: Position +} + export interface Position { /** >= 1 */ line: number @@ -217,7 +223,7 @@ export type Declaration = FunctionDeclaration | VariableDeclaration | ClassDecla type BaseDeclaration = BaseStatement -export interface FunctionDeclaration extends BaseFunction, BaseDeclaration { +export interface MaybeNamedFunctionDeclaration extends BaseFunction, BaseDeclaration { type: 'FunctionDeclaration' /** It is null when a function declaration is a part of the `export default function` statement */ id: Identifier | null @@ -226,6 +232,10 @@ export interface FunctionDeclaration extends BaseFunction, BaseDeclaration { returnType?: TSTypeAnnotation } +export interface FunctionDeclaration extends MaybeNamedFunctionDeclaration { + id: Identifier +} + export interface VariableDeclaration extends BaseDeclaration { type: 'VariableDeclaration' declarations: Array @@ -486,6 +496,9 @@ export type AssignmentOperator = | '|=' | '^=' | '&=' + | '||=' + | '&&=' + | '??=' export type UpdateOperator = '++' | '--' @@ -588,12 +601,16 @@ export interface MethodDefinition extends BaseNode { static: boolean } -export interface ClassDeclaration extends BaseClass, BaseDeclaration { +export interface MaybeNamedClassDeclaration extends BaseClass, BaseDeclaration { type: 'ClassDeclaration' /** It is null when a class declaration is a part of the `export default class` statement */ id: Identifier | null } +export interface ClassDeclaration extends MaybeNamedClassDeclaration { + id: Identifier +} + export interface ClassExpression extends BaseClass, BaseExpression { type: 'ClassExpression' id?: Identifier | null | undefined @@ -659,7 +676,7 @@ export interface ExportSpecifier extends BaseModuleSpecifier { export interface ExportDefaultDeclaration extends BaseModuleDeclaration { type: 'ExportDefaultDeclaration' - declaration: Declaration | Expression + declaration: MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration | Expression } export interface ExportAllDeclaration extends BaseModuleDeclaration { diff --git a/src/typeChecker/typeErrorChecker.ts b/src/typeChecker/typeErrorChecker.ts index 4bc55beca..2f5a922a7 100644 --- a/src/typeChecker/typeErrorChecker.ts +++ b/src/typeChecker/typeErrorChecker.ts @@ -534,6 +534,8 @@ function typeCheckAndReturnType(node: tsEs.Node): Type { return typeToCastTo case 'TSInterfaceDeclaration': throw new TypecheckError(node, 'Interface declarations are not allowed') + case 'ExportNamedDeclaration': + return typeCheckAndReturnType(node.declaration!) default: throw new TypecheckError(node, 'Unknown node type') } diff --git a/src/types.ts b/src/types.ts index efecebbde..5002820a3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -320,7 +320,11 @@ export interface StatementSequence extends es.BaseStatement { /** * js-slang's custom Node type - this should be used wherever es.Node is used. */ -export type Node = es.Node | StatementSequence +export type Node = + | es.Node + | StatementSequence + | es.MaybeNamedClassDeclaration + | es.MaybeNamedFunctionDeclaration /* Although the ESTree specifications supposedly provide a Directive interface, the index file does not seem to export it. diff --git a/src/utils/ast/astCreator.ts b/src/utils/ast/astCreator.ts index 61b404645..6e7318cae 100644 --- a/src/utils/ast/astCreator.ts +++ b/src/utils/ast/astCreator.ts @@ -340,7 +340,7 @@ export const functionDeclarationExpression = ( }) export const functionDeclaration = ( - id: es.Identifier | null, + id: es.Identifier, params: es.Pattern[], body: es.BlockStatement, loc?: es.SourceLocation | null diff --git a/yarn.lock b/yarn.lock index 1c41c0f5a..f8522b26f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1459,10 +1459,10 @@ dependencies: "@babel/types" "^7.20.7" -"@types/estree@0.0.52": - version "0.0.52" - resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.52.tgz" - integrity sha512-BZWrtCU0bMVAIliIV+HJO1f1PR41M7NKjfxrFJwwhKI1KwhwOxYw1SXg9ao+CIMt774nFuGiG6eU+udtbEI9oQ== +"@types/estree@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/graceful-fs@^4.1.3": version "4.1.9"