* Copyright (c) 2023-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 "packageImplicitImport.h"
#include <generated/diagnostic.h>
namespace ark::es2panda::compiler {
static void MergeExternalFilesIntoCompiledProgram(parser::PackageProgram *const package)
{
ES2PANDA_ASSERT(package->Ast() != nullptr);
ES2PANDA_ASSERT(package->Ast()->Statements().empty());
for (auto *const extProg : package->GetUnmergedPackagePrograms()) {
for (auto *const stmt : extProg->Ast()->Statements()) {
if (stmt->IsETSPackageDeclaration()) {
continue;
}
stmt->SetParent(package->Ast());
package->Ast()->AddStatement(stmt);
}
}
package->GetUnmergedPackagePrograms().resize(0);
}
static void ValidateImportDeclarationsSourcePath(const public_lib::Context *const ctx,
const parser::PackageProgram *package,
const std::vector<const ir::Statement *> &importDeclarations)
{
for (const auto *const stmt : importDeclarations) {
auto *importManager = ctx->parser->GetImportPathManager();
auto *referencedProg = importManager->SearchResolved(stmt->AsETSImportDeclaration()->ImportInfo());
const bool doesImportFromPackage =
(referencedProg != nullptr) && (referencedProg->ModuleName() == package->ModuleName());
if (doesImportFromPackage) {
ctx->parser->LogError(diagnostic::PACKAGE_MODULE_IMPORT_OWN_PACKAGE, {}, stmt->Start());
}
}
}
static void ValidateNoImportComesFromSamePackage(const public_lib::Context *const ctx, parser::PackageProgram *package)
{
ES2PANDA_ASSERT(package->GetUnmergedPackagePrograms().empty());
{
std::vector<const ir::Statement *> importDeclarations {};
const auto &progStatements = package->Ast()->Statements();
std::copy_if(progStatements.begin(), progStatements.end(), std::back_inserter(importDeclarations),
[](const ir::Statement *const stmt) { return stmt->IsETSImportDeclaration(); });
ValidateImportDeclarationsSourcePath(ctx, package, importDeclarations);
}
}
bool PackageImplicitImport::Perform()
{
if (!Context()->parserProgram->Is<util::ModuleKind::PACKAGE>() || Context()->config->options->IsGenStdlib()) {
return true;
}
auto *package = Context()->parserProgram->As<util::ModuleKind::PACKAGE>();
auto &packagePrograms = package->GetUnmergedPackagePrograms();
std::stable_sort(packagePrograms.begin(), packagePrograms.end(),
[](const parser::Program *const prog1, const parser::Program *const prog2) {
return prog1->FileName() < prog2->FileName();
});
MergeExternalFilesIntoCompiledProgram(package);
ValidateNoImportComesFromSamePackage(Context(), package);
return true;
}
}