From b46681e340b6fd95f3b55993adfb2017b79c89d0 Mon Sep 17 00:00:00 2001 From: huangyu Date: Fri, 16 Jun 2023 14:52:17 +0800 Subject: [PATCH] fixed 2d16384 from https://gitee.com/huangyu76/arkcompiler_ets_frontend/pulls/1076 Support type record for import/export type in es2abc Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I7E195 Test: test/type_extractor/testcases_with_assert/projects, test/parser/ts Signed-off-by: huangyu Change-Id: I5c6261cbca79f49ac57295a7606769f01a172554 --- es2panda/parser/parserImpl.cpp | 5 +++ es2panda/parser/parserImpl.h | 6 ++- es2panda/parser/program/program.cpp | 2 + es2panda/parser/program/program.h | 6 +++ es2panda/parser/statementParser.cpp | 22 ++++----- .../ts/test-import-type-source-expected.txt | 1 + .../test/parser/ts/test-import-type-source.ts | 17 +++++++ .../test-export-default-type/export.ts | 17 +++++++ .../test-export-default-type/import-main.ts | 23 ++++++++++ .../test-import-export-type/export.ts | 45 +++++++++++++++++++ .../test-import-export-type/import-main.ts | 41 +++++++++++++++++ .../typescript/extractor/typeExtractor.cpp | 19 ++++++++ es2panda/typescript/extractor/typeExtractor.h | 2 + 13 files changed, 193 insertions(+), 13 deletions(-) create mode 100644 es2panda/test/parser/ts/test-import-type-source-expected.txt create mode 100644 es2panda/test/parser/ts/test-import-type-source.ts create mode 100644 es2panda/test/type_extractor/testcases_with_assert/projects/test-export-default-type/export.ts create mode 100644 es2panda/test/type_extractor/testcases_with_assert/projects/test-export-default-type/import-main.ts create mode 100644 es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export-type/export.ts create mode 100644 es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export-type/import-main.ts diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index d8b9442eb2..ee42125108 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -3706,6 +3706,11 @@ parser::SourceTextModuleRecord *ParserImpl::GetSourceTextModuleRecord() return Binder()->Program()->ModuleRecord(); } +parser::SourceTextModuleRecord *ParserImpl::GetSourceTextTypeModuleRecord() +{ + return Binder()->Program()->TypeModuleRecord(); +} + void ParserImpl::AddPatchFixHelper(util::PatchFix *patchFixHelper) { program_.AddPatchFixHelper(patchFixHelper); diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index f10f6c61e0..d71abfaa51 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -435,8 +435,9 @@ private: bool IsLabelFollowedByIterationStatement(); - void AddImportEntryItem(const ir::StringLiteral *source, const ArenaVector *specifiers); - void AddExportNamedEntryItem(const ArenaVector &specifiers, const ir::StringLiteral *source); + void AddImportEntryItem(const ir::StringLiteral *source, const ArenaVector *specifiers, bool isType); + void AddExportNamedEntryItem(const ArenaVector &specifiers, + const ir::StringLiteral *source, bool isType); void AddExportStarEntryItem(const lexer::SourcePosition &startLoc, const ir::StringLiteral *source, const ir::Identifier *exported); void AddExportDefaultEntryItem(const ir::AstNode *declNode); @@ -444,6 +445,7 @@ private: void AddTsTypeExportLocalEntryItem(const ir::Statement *declNode, bool isTsModule, binder::TSModuleScope *tsModuleScope); parser::SourceTextModuleRecord *GetSourceTextModuleRecord(); + parser::SourceTextModuleRecord *GetSourceTextTypeModuleRecord(); bool ParseDirective(ArenaVector *statements); void ParseDirectivePrologue(ArenaVector *statements); diff --git a/es2panda/parser/program/program.cpp b/es2panda/parser/program/program.cpp index 85ba31f9c7..e79d52d723 100644 --- a/es2panda/parser/program/program.cpp +++ b/es2panda/parser/program/program.cpp @@ -41,6 +41,7 @@ Program::Program(Program &&other) extension_(other.extension_), lineIndex_(other.lineIndex_), moduleRecord_(other.moduleRecord_), + typeModuleRecord_(other.typeModuleRecord_), patchFixHelper_(other.patchFixHelper_), isDtsFile_(other.isDtsFile_) { @@ -72,6 +73,7 @@ void Program::SetKind(ScriptKind kind) if (kind == ScriptKind::MODULE) { moduleRecord_ = allocator_->New(Allocator()); + typeModuleRecord_ = allocator_->New(Allocator()); } } diff --git a/es2panda/parser/program/program.h b/es2panda/parser/program/program.h index 1ec17485ca..f1f8602239 100644 --- a/es2panda/parser/program/program.h +++ b/es2panda/parser/program/program.h @@ -80,6 +80,11 @@ public: return moduleRecord_; } + SourceTextModuleRecord *TypeModuleRecord() const + { + return typeModuleRecord_; + } + util::StringView SourceCode() const { return sourceCode_.View(); @@ -165,6 +170,7 @@ private: ScriptExtension extension_ {}; lexer::LineIndex lineIndex_ {}; SourceTextModuleRecord *moduleRecord_ {nullptr}; + SourceTextModuleRecord *typeModuleRecord_ {nullptr}; util::PatchFix *patchFixHelper_ {nullptr}; bool isDtsFile_ {false}; }; diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index bc5878b207..52d7cf6cf8 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -2142,18 +2142,22 @@ ir::WhileStatement *ParserImpl::ParseWhileStatement() return whileStatement; } -void ParserImpl::AddImportEntryItem(const ir::StringLiteral *source, const ArenaVector *specifiers) +void ParserImpl::AddImportEntryItem(const ir::StringLiteral *source, + const ArenaVector *specifiers, bool isType) { if (context_.IsTsModule()) { return; } ASSERT(source != nullptr); - auto *moduleRecord = GetSourceTextModuleRecord(); + auto *moduleRecord = isType ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord(); ASSERT(moduleRecord != nullptr); auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str()); if (specifiers == nullptr) { + if (isType) { + ThrowSyntaxError("Unexpected import type syntax", source->Start()); + } return; } @@ -2194,14 +2198,14 @@ void ParserImpl::AddImportEntryItem(const ir::StringLiteral *source, const Arena } void ParserImpl::AddExportNamedEntryItem(const ArenaVector &specifiers, - const ir::StringLiteral *source) + const ir::StringLiteral *source, bool isType) { // The exported objects in the TSModuleScope do not need to be allocated index. if (context_.IsTsModule()) { ASSERT(Binder()->GetScope()->IsTSModuleScope()); return; } - auto moduleRecord = GetSourceTextModuleRecord(); + auto moduleRecord = isType ? GetSourceTextTypeModuleRecord() : GetSourceTextModuleRecord(); ASSERT(moduleRecord != nullptr); if (source) { auto moduleRequestIdx = moduleRecord->AddModuleRequest(source->Str()); @@ -2520,9 +2524,7 @@ ir::ExportNamedDeclaration *ParserImpl::ParseExportNamedSpecifiers(const lexer:: } // record ExportEntry - if (!isType) { - AddExportNamedEntryItem(specifiers, source); - } + AddExportNamedEntryItem(specifiers, source, isType); auto *exportDeclaration = AllocNode(source, std::move(specifiers), isType); exportDeclaration->SetRange({startLoc, endPos}); @@ -2999,13 +3001,11 @@ ir::Statement *ParserImpl::ParseImportDeclaration(StatementParsingFlags flags) return astNode->AsTSImportEqualsDeclaration(); } source = ParseFromClause(true); - if (!isType) { - AddImportEntryItem(source, &specifiers); - } + AddImportEntryItem(source, &specifiers, isType); } else { // import 'source' source = ParseFromClause(false); - AddImportEntryItem(source, nullptr); + AddImportEntryItem(source, nullptr, isType); } lexer::SourcePosition endLoc = source->End(); diff --git a/es2panda/test/parser/ts/test-import-type-source-expected.txt b/es2panda/test/parser/ts/test-import-type-source-expected.txt new file mode 100644 index 0000000000..253e24ed13 --- /dev/null +++ b/es2panda/test/parser/ts/test-import-type-source-expected.txt @@ -0,0 +1 @@ +SyntaxError: Unexpected token. [test-import-type-source.ts:17:13] diff --git a/es2panda/test/parser/ts/test-import-type-source.ts b/es2panda/test/parser/ts/test-import-type-source.ts new file mode 100644 index 0000000000..492685d3fb --- /dev/null +++ b/es2panda/test/parser/ts/test-import-type-source.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import type './export' diff --git a/es2panda/test/type_extractor/testcases_with_assert/projects/test-export-default-type/export.ts b/es2panda/test/type_extractor/testcases_with_assert/projects/test-export-default-type/export.ts new file mode 100644 index 0000000000..16128589ba --- /dev/null +++ b/es2panda/test/type_extractor/testcases_with_assert/projects/test-export-default-type/export.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +export default interface I{}; diff --git a/es2panda/test/type_extractor/testcases_with_assert/projects/test-export-default-type/import-main.ts b/es2panda/test/type_extractor/testcases_with_assert/projects/test-export-default-type/import-main.ts new file mode 100644 index 0000000000..3b6beaf142 --- /dev/null +++ b/es2panda/test/type_extractor/testcases_with_assert/projects/test-export-default-type/import-main.ts @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import type I from './export' + +function foo(i: I): I { + return i; +} + +AssertType(foo, "(interface) => interface"); diff --git a/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export-type/export.ts b/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export-type/export.ts new file mode 100644 index 0000000000..a357e7298d --- /dev/null +++ b/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export-type/export.ts @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +export default class Student { + name: string; + age: number; + constructor(name: string, age: number) { + this.name = name; + this.age = age; + }; +} + +class Particle { + public row: number = 0; + public col: number = 0; +} + +interface Lesson { + id: number, + date: string, + students: Student[] +} + +export type Klass = { + date: number; + name: string; +} + +export type customType = Student; + +export type { Particle }; +export { Lesson }; diff --git a/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export-type/import-main.ts b/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export-type/import-main.ts new file mode 100644 index 0000000000..52ab38bfa7 --- /dev/null +++ b/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export-type/import-main.ts @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import type Student from './export'; +import type { Particle, Lesson, Klass, customType } from './export'; + +declare function AssertType(value: any, type: string): void; + +function test(s: Student, p: Particle, l: Lesson, k: Klass, c: customType): void { +} + +function init(p: Particle): void { + p.row = 1; + p.col = 2; +} + +let students: Student[]; +const math: Lesson = { + id: 0, + date: "2023", + students +} + +AssertType(test, "(Student, Particle, interface, object, Student) => void"); +AssertType(init, "(Particle) => void"); +AssertType(math.id, "number"); +AssertType(math.date, "string"); +AssertType(math.students, "Student[]"); diff --git a/es2panda/typescript/extractor/typeExtractor.cpp b/es2panda/typescript/extractor/typeExtractor.cpp index 17dfc58ee5..c231afd639 100644 --- a/es2panda/typescript/extractor/typeExtractor.cpp +++ b/es2panda/typescript/extractor/typeExtractor.cpp @@ -167,7 +167,17 @@ void TypeExtractor::ExtractImport(const parser::Program *program) if (moduleRecord == nullptr) { return; } + ExtractImportModuleRecord(moduleRecord); + auto typeModuleRecord = program->Binder()->Program()->TypeModuleRecord(); + if (typeModuleRecord == nullptr) { + return; + } + ExtractImportModuleRecord(typeModuleRecord); +} + +void TypeExtractor::ExtractImportModuleRecord(parser::SourceTextModuleRecord *moduleRecord) +{ const auto ®ularImportEntries = moduleRecord->GetRegularImportEntries(); for (const auto &t : regularImportEntries) { const auto &redirectPath = moduleRecord->GetModuleRequestIdxMap().at(t.second->moduleRequestIdx_); @@ -190,7 +200,16 @@ void TypeExtractor::ExtractExport(const parser::Program *program) if (moduleRecord == nullptr) { return; } + ExtractExportModuleRecord(moduleRecord); + auto typeModuleRecord = program->Binder()->Program()->TypeModuleRecord(); + if (typeModuleRecord == nullptr) { + return; + } + ExtractExportModuleRecord(typeModuleRecord); +} +void TypeExtractor::ExtractExportModuleRecord(parser::SourceTextModuleRecord *moduleRecord) +{ const auto &localExportEntries = moduleRecord->GetLocalExportEntries(); for (const auto &t : localExportEntries) { auto identifier = t.second->localId_; diff --git a/es2panda/typescript/extractor/typeExtractor.h b/es2panda/typescript/extractor/typeExtractor.h index e51345e28f..a8c3699e49 100644 --- a/es2panda/typescript/extractor/typeExtractor.h +++ b/es2panda/typescript/extractor/typeExtractor.h @@ -72,6 +72,8 @@ private: void ExtractNodeType(const ir::AstNode *parent, const ir::AstNode *childNode); void ExtractImport(const parser::Program *program); void ExtractExport(const parser::Program *program); + void ExtractImportModuleRecord(parser::SourceTextModuleRecord *moduleRecord); + void ExtractExportModuleRecord(parser::SourceTextModuleRecord *moduleRecord); const ir::AstNode *GetDeclNodeFromIdentifier(const ir::Identifier *identifier, const ir::Identifier **variable); const ir::AstNode *GetDeclNodeFromInitializer(const ir::Expression *initializer, const ir::Identifier **variable); -- Gitee