// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Windows.Forms; namespace Flax.Stats { /// /// Single code frame data /// public sealed class CodeFrameNode : IDisposable { private static string[] ignoredFolders = new[] { ".vs", ".git", "obj", "bin", "packages", "thirdparty", "3rdparty", "flaxdeps", "platforms", "flaxapi", }; /// /// Array with all child nodes /// public CodeFrameNode[] Children; /// /// Amount of lines of code /// public long[] LinesOfCode; /// /// Size of the node on the hard drive /// public long SizeOnDisk; /// /// Amount of files /// public int FilesCount; /// /// Short directory name /// public string ShortName; /// /// Gets total amount of lines of code in that node and all child nodes /// public long TotalLinesOfCode { get { long result = 0; for (int i = 0; i < (int)Languages.Max; i++) { result += LinesOfCode[i]; } for (int i = 0; i < Children.Length; i++) { result += Children[i].TotalLinesOfCode; } return result; } } /// /// Gets total amount of memory used by that node and all child nodes /// public long TotalSizeOnDisk { get { long result = SizeOnDisk; for (int i = 0; i < Children.Length; i++) { result += Children[i].TotalSizeOnDisk; } return result; } } /// /// Gets total amount of files used by that node and all child nodes /// public long TotalFiles { get { long result = FilesCount; for (int i = 0; i < Children.Length; i++) { result += Children[i].TotalFiles; } return result; } } /// /// Gets code frame node with given index /// /// Code frame node index /// Code frame node public CodeFrameNode this[int index] { get { return Children[index]; } } /// /// Gets code frame node with given name /// /// Code frame node index /// Code frame node public CodeFrameNode this[string name] { get { for (int i = 0; i < Children.Length; i++) if (Children[i].ShortName == name) return Children[i]; return null; } } /// /// Init /// /// Directory name /// Amount of files /// Lines of code /// Size on disk /// Child nodes public CodeFrameNode(string name, int filesCnt, long[] lines, long size, CodeFrameNode[] children) { if(lines == null || lines.Length != (int)Languages.Max) throw new InvalidDataException(); ShortName = name; FilesCount = filesCnt; Children = children; LinesOfCode = lines; SizeOnDisk = size; } /// /// Gets total amount of lines of code per language /// /// Language /// Result amount of lines public long GetTotalLinesOfCode(Languages language) { long result = 0; result += LinesOfCode[(int)language]; for (int i = 0; i < Children.Length; i++) { result += Children[i].GetTotalLinesOfCode(language); } return result; } /// /// Capture data from the folder /// /// Folder path to capture /// Created code frame of null if cannot create that public static CodeFrameNode Capture(DirectoryInfo folder) { // Get all files from that folder FileInfo[] files; try { files = folder.GetFiles("*.*"); } catch (UnauthorizedAccessException) { return null; } catch (Exception exception) { MessageBox.Show(exception.Message); return null; } // Count data long[] lines = new long[(int)Languages.Max]; for (int i = 0; i < (int)Languages.Max; i++) { lines[i] = 0; } long size = 0; for (int i = 0; i < files.Length; i++) { // Count files size size += files[i].Length; // Get file type index int index = -1; switch (files[i].Extension) { // C++ case ".h": case ".cpp": case ".cxx": case ".hpp": case ".hxx": case ".c": index = (int)Languages.Cpp; break; // C# case ".cs": index = (int)Languages.CSharp; break; // HLSL case ".hlsl": case ".shader": index = (int)Languages.Hlsl; break; } if (index == -1) continue; // Count lines in the source file long ll = 1; using (StreamReader streamReader = new StreamReader(files[i].FullName)) { while (streamReader.ReadLine() != null) { ll++; } } lines[index] += ll; } // Get all directories DirectoryInfo[] directories = folder.GetDirectories(); if (directories.Length == 0 && files.Length == 0) { // Empty folder return null; } // Process child nodes List children = new List(directories.Length); for (int i = 0; i < directories.Length; i++) { // Validate name if(ignoredFolders.Contains(directories[i].Name.ToLower())) continue; var child = Capture(directories[i]); if (child != null) { children.Add(child); } } // Create node return new CodeFrameNode(folder.Name, files.Length, lines, size, children.ToArray()); } public void CleanupDirectories() { var child = Children.ToList(); child.RemoveAll(e => ignoredFolders.Contains(e.ShortName.ToLower())); Children = child.ToArray(); foreach (var a in Children) { a.CleanupDirectories(); } } /// /// Clean all data /// public void Dispose() { if (Children != null) { // Clear for (int i = 0; i < Children.Length; i++) { Children[i].Dispose(); } Children = null; } } /// /// To string /// /// String public override string ToString() { return ShortName; } } }