public void Analyse(string basePath, string version, FunctionOptions options)
        {
            BasePath = basePath;
            Options  = options;
            if (!Directory.Exists(BasePath))
            {
                Logger.Log(MessageProvider.FolderDoesNotExist(BasePath));
                return;
            }

            Logger.Log(MessageProvider.AnalyseFunctions(BasePath, Versions[version]));
            Stopwatch    timer   = Stopwatch.StartNew();
            FunctionData results = AnalyseFunctions(version);

            timer.Stop();

            Logger.Log(MessageProvider.Time(timer));
            Report(results);
        }
        private static void AnalyseArgument(ParsedArgument argument, FunctionData data, bool firstArgument, bool inSelector)
        {
            object result = argument.GetResult();

            if (argument.IsFromRoot())
            {
                if (result is Literal literal)
                {
                    data.UsedCommands.Increase(literal.Value, !firstArgument);
                }
            }
            else if (result is Function)
            {
                data.FunctionCalls.Increase();
            }
            else if (result is EntitySelector entitySelector)
            {
                AnalyseSelector(entitySelector, data);
            }
            else if (result is ScoreHolder scoreHolder && scoreHolder.Selector != null)
            {
                AnalyseSelector(scoreHolder.Selector, data);
            }
        private FunctionData AnalyseFunction(string path, string version)
        {
            // Data to return
            FunctionData functionData = new FunctionData();

            // Lines
            string[] lines = File.ReadAllLines(path);

            // Errors
            Dictionary <int, CommandError> errors = new Dictionary <int, CommandError>();

            for (int i = 0; i < lines.Length; i++)
            {
                string command = lines[i].Trim();

                if (string.IsNullOrEmpty(command))
                {
                    // Empty line
                    functionData.EmptyLines.Increase();
                    continue;
                }
                else if (command.StartsWith('#'))
                {
                    // Comment
                    functionData.Comments.Increase();
                    continue;
                }
                else
                {
                    CommandResults commandResults = Versions[version].Parse(command);
                    if (commandResults.Successful)
                    {
                        functionData.Commands.Increase();
                        // Analyse Arguments
                        bool isFirstArgument = true;
                        for (int j = 0; j < commandResults.Arguments.Count; j++)
                        {
                            AnalyseArgument(commandResults.Arguments[j], functionData, isFirstArgument, false);
                            isFirstArgument = false;
                        }
                    }
                    else
                    {
                        // Error
                        errors.Add(i, commandResults.Error);
                        if (Options.SkipFunctionOnError)
                        {
                            break;
                        }
                    }
                }
            }

            if (errors.Count > 0)
            {
                if (Options.ShowCommandErrors)
                {
                    functionData.Messages.Add(MessageProvider.ErrorsFound(errors.Count, GetShortFileName(path), Options.SkipFunctionOnError));
                    foreach (KeyValuePair <int, CommandError> kvp in errors)
                    {
                        functionData.Messages.Add(MessageProvider.Error(kvp.Key + 1, kvp.Value));
                    }
                }
                if (Options.SkipFunctionOnError)
                {
                    return(functionData);
                }
            }
            else if (functionData.Commands.GetTotal() == 0)
            {
                if (Options.ShowEmptyFunctions)
                {
                    functionData.Messages.Add(MessageProvider.EmptyFunction(GetShortFileName(path)));
                }
            }

            functionData.Functions.Increase();
            return(functionData);
        }