You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Tools/AssetProcessor/native/utilities/MissingDependencyScanner.h

171 lines
7.1 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/std/containers/set.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/string/regex.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzToolsFramework/AssetDatabase/AssetDatabaseConnection.h>
#include <AzToolsFramework/Asset/AssetUtils.h>
#include <native/utilities/ApplicationManagerAPI.h>
namespace AZ
{
namespace IO
{
class GenericStream;
}
}
namespace AssetProcessor
{
class AssetDatabaseConnection;
class LineByLineDependencyScanner;
class MissingDependency;
class PotentialDependencies;
class SpecializedDependencyScanner;
typedef AZStd::set<MissingDependency> MissingDependencies;
enum class ScannerMatchType
{
// The scanner to run only matches based on the file extension, such as a "json" scanner will only
// scan files with the .json extension.
ExtensionOnlyFirstMatch,
// The scanners open each file and inspect the contents to see if they look like the format.
// The first scanner found that matches the file will be used.
// Example: If a file named "Medium.difficulty" is in XML format, the XML scanner will catch this and scan it.
FileContentsFirstMatch,
// All scanners that can scan the given file are used to scan it. Time consuming but thorough.
Deep
};
class MissingDependencyScannerRequests
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// Bus configuration
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
using MutexType = AZStd::mutex;
/**
* Scans the given file for a missing dependency. Note that the database connection is
* not the AzToolsFramework version, it is the AssetProcessor version. This command needs
* write access to the database.
*/
using scanFileCallback = AZStd::function<void(AZStd::string relativeDependencyFilePath)>;
virtual void ScanFile(
const AZStd::string& fullPath,
int maxScanIteration,
AZ::s64 productPK,
const AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& dependencies,
AZStd::shared_ptr<AssetDatabaseConnection> databaseConnection,
bool queueDbCommandsOnMainThread,
scanFileCallback callback) = 0;
};
using MissingDependencyScannerRequestBus = AZ::EBus<MissingDependencyScannerRequests>;
class MissingDependencyScanner
: public MissingDependencyScannerRequestBus::Handler
, AssetProcessor::ApplicationManagerNotifications::Bus::Handler
{
public:
MissingDependencyScanner();
~MissingDependencyScanner() override;
// ApplicationManagerNotifications::Bus::Handler
void ApplicationShutdownRequested() override;
//! Scans the file at the fullPath for anything that looks like a missing dependency.
//! Reporting is handled internally, no results are returned.
//! Anything that matches a result in the given dependency list will not be reported as a missing dependency.
//! The databaseConnection is used to query the database to transform relative paths into source or
//! product assets that match those paths, as well as looking up products for UUIDs found in files.
//! The matchtype is used to determine how to scan the given file, see the ScannerMatchType enum for more information.
//! A specific scanner can be forced to be used, this will supercede the match type.
void ScanFile(
const AZStd::string& fullPath,
int maxScanIteration,
AZ::s64 productPK,
const AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& dependencies,
AZStd::shared_ptr<AssetDatabaseConnection> databaseConnection,
bool queueDbCommandsOnMainThread,
scanFileCallback callback) override;
void ScanFile(const AZStd::string& fullPath,
int maxScanIteration,
AZStd::shared_ptr<AssetDatabaseConnection> databaseConnection,
const AZStd::string& dependencyTokenName,
bool queueDbCommandsOnMainThread,
scanFileCallback callback);
void ScanFile(
const AZStd::string& fullPath,
int maxScanIteration,
AZ::s64 productPK,
const AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& dependencies,
AZStd::shared_ptr<AssetDatabaseConnection> databaseConnection,
AZStd::string dependencyTokenName,
ScannerMatchType matchType,
AZ::Crc32* forceScanner,
bool queueDbCommandsOnMainThread,
scanFileCallback callback);
static const int DefaultMaxScanIteration;
void RegisterSpecializedScanner(AZStd::shared_ptr<SpecializedDependencyScanner> scanner);
bool PopulateRulesForScanFolder(const AZStd::string& scanFolderPath, const AZStd::vector<AzFramework::GemInfo>& gemInfoList, AZStd::string& dependencyTokenName);
protected:
bool RunScan(
const AZStd::string& fullPath,
int maxScanIteration,
AZ::IO::GenericStream& fileStream,
PotentialDependencies& potentialDependencies,
ScannerMatchType matchType,
AZ::Crc32* forceScanner);
void PopulateMissingDependencies(
AZ::s64 productPK,
AZStd::shared_ptr<AssetDatabaseConnection> databaseConnection,
const AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& dependencies,
MissingDependencies& missingDependencies,
const PotentialDependencies& potentialDependencies);
void ReportMissingDependencies(
AZ::s64 productPK,
AZStd::shared_ptr<AssetDatabaseConnection> databaseConnection,
const AZStd::string& dependencyTokenName,
const MissingDependencies& missingDependencies,
scanFileCallback callback);
void SetDependencyScanResultStatus(
AZStd::string status,
AZ::s64 productPK,
const AZStd::string& analysisFingerprint,
AZStd::shared_ptr<AssetDatabaseConnection> databaseConnection,
bool queueDbCommandsOnMainThread,
scanFileCallback callback);
typedef AZStd::unordered_map<AZ::Crc32, AZStd::shared_ptr<SpecializedDependencyScanner>> DependencyScannerMap;
DependencyScannerMap m_specializedScanners;
AZStd::shared_ptr<LineByLineDependencyScanner> m_defaultScanner;
AZStd::unordered_map<AZStd::string, AZStd::vector<AZStd::string>> m_dependenciesRulesMap;
AZStd::atomic_bool m_shutdownRequested = false;
};
}