using System; using System.Linq; using EpicGames.UHT.Types; namespace UnrealSharpScriptGenerator.Tooltip; public static class TooltipParser { private static void ParseTooltip(string inTooltip, ref ParsedTooltip outParsedTooltip) { string sourceTooltip = inTooltip; int sourceTooltipParseIndex = 0; void SkipToNextToken() { while (sourceTooltipParseIndex < sourceTooltip.Length && (char.IsWhiteSpace(sourceTooltip[sourceTooltipParseIndex]) || sourceTooltip[sourceTooltipParseIndex] == '-')) { ++sourceTooltipParseIndex; } } var tokenStartIndex = sourceTooltipParseIndex; void ParseSimpleToken(ref ParsedTooltip.TokenString outToken) { while (sourceTooltipParseIndex < sourceTooltip.Length && !char.IsWhiteSpace(sourceTooltip[sourceTooltipParseIndex])) { ++sourceTooltipParseIndex; } outToken.SimpleValue = sourceTooltip.Substring(tokenStartIndex, sourceTooltipParseIndex - tokenStartIndex); } void ParseComplexToken(ref ParsedTooltip.TokenString outToken) { int startIndex = sourceTooltipParseIndex; while (sourceTooltipParseIndex < sourceTooltip.Length && sourceTooltip[sourceTooltipParseIndex] != '@') { if (char.IsWhiteSpace(sourceTooltip[sourceTooltipParseIndex])) { if (startIndex != -1) { outToken.ComplexValue = sourceTooltip.Substring(startIndex, sourceTooltipParseIndex - startIndex); startIndex = -1; } while (sourceTooltipParseIndex < sourceTooltip.Length && char.IsWhiteSpace(sourceTooltip[sourceTooltipParseIndex])) { ++sourceTooltipParseIndex; } while (sourceTooltipParseIndex < sourceTooltip.Length && char.IsWhiteSpace(sourceTooltip[sourceTooltipParseIndex])) { ++sourceTooltipParseIndex; } outToken.ComplexValue += ' '; } if (sourceTooltipParseIndex < sourceTooltip.Length && sourceTooltip[sourceTooltipParseIndex] != '@') { if (startIndex == -1) { outToken.ComplexValue += sourceTooltip[sourceTooltipParseIndex]; } ++sourceTooltipParseIndex; } } if (startIndex == -1) { outToken.ComplexValue = outToken.ComplexValue.TrimEnd(); } else { outToken.SimpleValue = sourceTooltip.Substring(startIndex, sourceTooltipParseIndex - startIndex); outToken.SimpleValue = outToken.SimpleValue.TrimEnd(); } } while (sourceTooltipParseIndex < sourceTooltip.Length) { if (sourceTooltip[sourceTooltipParseIndex] == '@') { ++sourceTooltipParseIndex; if (sourceTooltipParseIndex < sourceTooltip.Length && sourceTooltip[sourceTooltipParseIndex] == '@') { outParsedTooltip.BasicTooltipText += '@'; ++sourceTooltipParseIndex; continue; } var tokenName = new ParsedTooltip.TokenString(); SkipToNextToken(); ParseSimpleToken(ref tokenName); if (tokenName.Value == "param") { var paramToken = new ParsedTooltip.ParamToken(); SkipToNextToken(); ParseSimpleToken(ref paramToken.ParamName); SkipToNextToken(); ParseComplexToken(ref paramToken.ParamComment); outParsedTooltip.ParamTokens.Add(paramToken); } else if (tokenName.Value is "return" or "returns") { SkipToNextToken(); ParseComplexToken(ref outParsedTooltip.ReturnToken.ParamComment); } else { var miscToken = new ParsedTooltip.MiscToken { TokenName = tokenName }; SkipToNextToken(); ParseComplexToken(ref miscToken.TokenValue); outParsedTooltip.MiscTokens.Add(miscToken); } } else { outParsedTooltip.BasicTooltipText += sourceTooltip[sourceTooltipParseIndex++]; } } } public static void AppendTooltip(this GeneratorStringBuilder builder, string toolTip) { if (string.IsNullOrEmpty(toolTip)) { return; } ParsedTooltip parsedTooltip = new(); ParseTooltip(toolTip, ref parsedTooltip); if (!string.IsNullOrEmpty(parsedTooltip.BasicTooltipText)) { string[] lines = parsedTooltip.BasicTooltipText.Split(new[] { '\n' }, StringSplitOptions.None); builder.AppendLine("/// "); foreach (var line in lines) { builder.AppendLine($"/// {line}"); } builder.AppendLine("/// "); } if (parsedTooltip.ParamTokens.Any()) { foreach (var miscToken in parsedTooltip.ParamTokens) { builder.AppendLine($"/// {miscToken.ParamComment.Value}"); } } var returnToolTip = parsedTooltip.ReturnToken.ParamComment.Value; if (string.IsNullOrEmpty(returnToolTip)) { return; } builder.AppendLine("/// "); builder.Append(returnToolTip); builder.Append(""); } public static void AppendTooltip(this GeneratorStringBuilder builder, UhtType type) { string toolTip = type.GetToolTipText(); // Skip if the tooltip is just the same as the source name. UHT automatically generates these. if (toolTip == type.SourceName) { return; } AppendTooltip(builder, toolTip); } }