* Copyright (c) 2024-2026 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.
*/
#include "evaluate/scopedDebugInfoPlugin-inl.h"
#include "evaluate/entityDeclarator.h"
#include "evaluate/irCheckHelper.h"
#include "parser/program/program.h"
#include "ir/expressions/identifier.h"
#include "ir/ets/etsImportDeclaration.h"
#include "ir/expressions/literals/stringLiteral.h"
#include "public/public.h"
#include "util/importPathManager.h"
namespace ark::es2panda::evaluate {
EntityDeclarator::EntityDeclarator(ScopedDebugInfoPlugin &debugInfoPlugin)
: debugInfoPlugin_(debugInfoPlugin),
createdEntities_(debugInfoPlugin_.GetIrCheckHelper()->GetChecker()->Allocator()->Adapter())
{
}
UMapStringViewVariable &EntityDeclarator::GetOrCreateEntitiesMap(parser::Program *program)
{
ES2PANDA_ASSERT(program);
auto iter = createdEntities_.find(program);
if (iter == createdEntities_.end()) {
auto adapter = debugInfoPlugin_.GetIrCheckHelper()->GetChecker()->Allocator()->Adapter();
return createdEntities_.emplace(program, UMapStringViewVariable(adapter)).first->second;
}
return iter->second;
}
void EntityDeclarator::CreateAndInsertImportStatement(util::StringView pathToDeclSource, util::StringView declName,
parser::Program *importerProgram, util::StringView importedName,
varbinder::Variable *var)
{
ES2PANDA_ASSERT(importerProgram);
ES2PANDA_ASSERT(var);
auto &importEntitiesMap = GetOrCreateEntitiesMap(importerProgram);
auto *findVar = FindEntityVariable(importEntitiesMap, importedName);
if (findVar != nullptr) {
ES2PANDA_ASSERT(findVar == var);
return;
}
auto *importStatement = CreateIrImport(pathToDeclSource, declName, importedName);
InsertImportStatement(importStatement, importerProgram);
if (!importEntitiesMap.emplace(importedName, var).second) {
LOG(FATAL, ES2PANDA) << "Failed to emplace " << importedName << " in entity map.";
}
}
ir::ETSImportDeclaration *EntityDeclarator::CreateIrImport(util::StringView pathToDeclSourceFile,
util::StringView classDeclName,
util::StringView classImportedName)
{
auto *checker = debugInfoPlugin_.GetIrCheckHelper()->GetChecker();
auto *allocator = checker->Allocator();
auto moduleName = debugInfoPlugin_.GetDebugInfoStorage()->GetModuleName(pathToDeclSourceFile.Utf8());
auto *source = checker->AllocNode<ir::StringLiteral>(moduleName);
auto importLanguage = ToLanguage(debugInfoPlugin_.GetETSBinder()->Extension());
util::ImportInfo importInfo {*debugInfoPlugin_.E2PContext()->parser->GetImportPathManager(),
pathToDeclSourceFile.Mutf8(), importLanguage.GetId()};
auto *local = checker->AllocNode<ir::Identifier>(classDeclName, allocator);
auto *imported = checker->AllocNode<ir::Identifier>(classImportedName, allocator);
auto *spec = checker->AllocNode<ir::ImportSpecifier>(imported, local);
ArenaVector<ir::AstNode *> specifiers(1, spec, allocator->Adapter());
return checker->AllocNode<ir::ETSImportDeclaration>(source, importInfo, std::move(specifiers));
}
void EntityDeclarator::InsertImportStatement(ir::Statement *importStatement, parser::Program *importerProgram)
{
ES2PANDA_ASSERT(importerProgram);
ES2PANDA_ASSERT(importStatement);
auto *topStatement = importerProgram->Ast();
importStatement->SetParent(topStatement);
debugInfoPlugin_.RegisterPrologueEpilogue<true>(topStatement, importStatement);
debugInfoPlugin_.GetIrCheckHelper()->CheckGlobalEntity(importerProgram, importStatement);
}
bool EntityDeclarator::IsEntityDeclared(parser::Program *program, util::StringView name)
{
ES2PANDA_ASSERT(program);
auto &entitiesMap = GetOrCreateEntitiesMap(program);
return entitiesMap.find(name) != entitiesMap.end();
}
varbinder::Variable *EntityDeclarator::FindEntityVariable(UMapStringViewVariable &entitiesMap,
util::StringView entityName)
{
const auto &find = entitiesMap.find(entityName);
if (find != entitiesMap.end()) {
return find->second;
}
return nullptr;
}
}