为代码文件的include关系生成Mermaid图

目标

类似《为代码中的类继承关系生成Mermaid图》
我想为代码文件的include关系生成Mermaid图。
为了排除不感兴趣的其他文件,我将从一个“根文件”出发,找出其include的文件,再递归依次找出他们的include文件。

概括思路

  1. 递归的方式找到一个文件夹下的所有代码文件,记为files
  2. 遍历files,读取每一行line
  3. 对于line做下面处理:(1)先看是否包含 #include ,如果不包含则跳过。(2)然后截取两个引号之间的字符串作为文件路径,处理后变为文件名。这样便能最终得到所有include关系数据
  4. 最后,根据include关系数据,从一个“根文件”出发,找出其include的文件,再递归依次找出他们的include文件。然后用Mermaid的格式打印出这些关系。

具体代码

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

//递归地方式找到所有的文件
void GetFilesInFolder_recursion(string folder, vector<string>& files)
{
     
	_finddata_t fileInfo;	//储存得到的文件信息
	//找第一个
	auto findResult = _findfirst((folder + "\\*").c_str(), &fileInfo);
	if (findResult == -1)
	{
     
		_findclose(findResult);
		return;
	}
	//找之后的
	do
	{
     
		string fileName = fileInfo.name;
		if ((fileInfo.attrib == _A_NORMAL) || (fileInfo.attrib == _A_ARCH))  //是文件
		{
     
			files.push_back(folder + "/" + fileName);
		}
		else if (fileInfo.attrib == _A_SUBDIR)//是文件夹
		{
     
			if (fileName == ".")	//跳过得到的这个路径
				continue;
			if (fileName == "..")	//跳过得到的这个路径
				continue;
			GetFilesInFolder_recursion(folder + "/" + fileName, files);
		}
	} while (_findnext(findResult, &fileInfo) == 0);

	_findclose(findResult);
}

//将路径转换为文件名
string GetFileNameFromPath(string filePath)
{
     
	//最后一个斜杠的位置:
	const int LastSlashIndex = filePath.find_last_of('/');
	
	if (LastSlashIndex == -1)//没找到
		return filePath;
	else
		return filePath.substr(LastSlashIndex + 1, filePath.size() - LastSlashIndex);
}

//递归的方式收集所有文件
void ColectIncludeFile_recursion(map<string, vector<string>>& InlcudeRelationships, const string fileName, set<string >& Collection)
{
     
	Collection.insert(fileName);
	for (string includeFile : InlcudeRelationships[fileName])
		ColectIncludeFile_recursion(InlcudeRelationships, includeFile, Collection);
}

int main()
{
     
	//搜寻的文件夹:
	const string Folder = "D:/0_WorkSpace/UnrealEngine-release/Engine/Shaders/Private";
	//查询的文件:
	const string RootFileName = "MaterialTemplate.ush";

	//包含关系:
	map<string, vector<string>> InlcudeRelationships;	

	//找到所有文件:
	vector<string> files;
	GetFilesInFolder_recursion(Folder, files);

	//收集所有的信息
	for (auto filePath : files)
	{
     
		//cout << "读取文件" << filePath << endl;
		
		//读取文件
		fstream fileStream(filePath);

		//文件名
		const string fileName = GetFileNameFromPath(filePath);

		//一行的内容字符串
		char line[1024] = {
      0 };

		//读取每一行
		while (fileStream.getline(line, 1024))
		{
     
			//转换为std::string类型
			string content = line;

			if (content.find("#include")!=-1)//如果存在include字样
			{
     
				//cout <<  content << endl;

				//第一个引号的位置:
				const int FirstIndex = content.find_first_of('"');
				//第二个引号的位置:
				const int SecondIndex = content.find_last_of('"');
				//文件路径就是两个引号之间的内容
				const string includePath = content.substr(FirstIndex + 1, SecondIndex - FirstIndex - 1);
				//cout << includePath << endl;

				//文件名字
				const string IncludeFile = GetFileNameFromPath(includePath);
				//cout << IncludeFile << endl;

				//添加进一个关系:
				InlcudeRelationships[fileName].push_back(IncludeFile);
			}
		}
	}

	//递归收集出所有Include关系
	set<string > Collection;
	ColectIncludeFile_recursion(InlcudeRelationships, RootFileName, Collection);

	//打印出所有的关系
	for (string f : Collection)
		for (string include : InlcudeRelationships[f])
			cout << f << "-->" << include << endl;
}

使用时:

  • main()中的Folder变量设置为所有相关代码所在的文件夹。
  • main()中的RootFileName变量设置为想要查询的“根”文件。

试用

尝试打印出UE4的shader文件中,MaterialTemplate.ush所include的文件关系:

Common.ush-->Platform.ush
Common.ush-->GeneratedUniformBuffers.ush
Common.ush-->CommonViewUniformBuffer.ush
Common.ush-->InstancedStereo.ush
Common.ush-->Definitions.usf
Common.ush-->FastMath.ush
Common.ush-->Random.ush
DeferredShadingCommon.ush-->ShadingCommon.ush
DeferredShadingCommon.ush-->LightAccumulator.ush
DeferredShadingCommon.ush-->SceneTexturesCommon.ush
InstancedStereo.ush-->View.ush
InstancedStereo.ush-->InstancedView.ush
InstancedStereo.ush-->GeneratedInstancedStereo.ush
MaterialTemplate.ush-->SceneTexturesCommon.ush
MaterialTemplate.ush-->Random.ush
MaterialTemplate.ush-->SobolRandom.ush
MaterialTemplate.ush-->MonteCarlo.ush
MaterialTemplate.ush-->Material.ush
MaterialTemplate.ush-->DepthOfFieldCommon.ush
MaterialTemplate.ush-->CircleDOFCommon.ush
MaterialTemplate.ush-->GlobalDistanceFieldShared.ush
MaterialTemplate.ush-->SceneData.ush
MaterialTemplate.ush-->SpeedTreeCommon.ush
MaterialTemplate.ush-->VirtualTextureCommon.ush
MaterialTemplate.ush-->MinMaterialTexCoords.ush
MaterialTemplate.ush-->AtmosphereCommon.ush
MaterialTemplate.ush-->SkyAtmosphereCommon.ush
MaterialTemplate.ush-->PaniniProjection.ush
MaterialTemplate.ush-->DeferredShadingCommon.ush
MonteCarlo.ush-->Common.ush
SceneTexturesCommon.ush-->Common.ush
SpeedTreeCommon.ush-->SpeedTreeData.ush
VirtualTextureCommon.ush-->Common.ush
VirtualTextureCommon.ush-->Random.ush

生成Mermaid图:

Common.ush
Platform.ush
GeneratedUniformBuffers.ush
CommonViewUniformBuffer.ush
InstancedStereo.ush
Definitions.usf
FastMath.ush
Random.ush
DeferredShadingCommon.ush
ShadingCommon.ush
LightAccumulator.ush
SceneTexturesCommon.ush
View.ush
InstancedView.ush
GeneratedInstancedStereo.ush
MaterialTemplate.ush
SobolRandom.ush
MonteCarlo.ush
Material.ush
DepthOfFieldCommon.ush
CircleDOFCommon.ush
GlobalDistanceFieldShared.ush
SceneData.ush
SpeedTreeCommon.ush
VirtualTextureCommon.ush
MinMaterialTexCoords.ush
AtmosphereCommon.ush
SkyAtmosphereCommon.ush
PaniniProjection.ush
SpeedTreeData.ush

你可能感兴趣的:(我的工具,c++)