private UnityApiEventFunction ParseMessage(ApiNode message, Version apiVersion, string hintNamespace) { var link = message.SelectOne(@"td.lbl/a"); var desc = message.SelectOne(@"td.desc"); if (link == null || desc == null) { return(null); } var detailsPath = link[@"href"]; if (string.IsNullOrWhiteSpace(detailsPath)) { return(null); } var path = Path.Combine(myScriptReferenceRelativePath, detailsPath); if (!File.Exists(path)) { return(null); } var detailsDoc = ApiNode.Load(path); var details = detailsDoc?.SelectOne(@"//div.content/div.section"); var signature = details?.SelectOne(@"div.mb20.clear/h1.heading.inherit"); var staticNode = details?.SelectOne(@"div.subsection/p/code.varname[text()='static']"); if (signature == null) { return(null); } var isCoroutine = CoroutineRegex.IsMatch(details.Text); var messageName = link.Text; var returnType = ApiType.Void; string[] argumentNames = null; var isStaticFromExample = false; var example = PickExample(details); if (example != null) { var tuple = ParseDetailsFromExample(messageName, example, hintNamespace); returnType = tuple.Item1; argumentNames = tuple.Item2; isStaticFromExample = tuple.Item3; } var docPath = Path.Combine(myScriptReferenceRelativePath, detailsPath); var eventFunction = new UnityApiEventFunction(messageName, staticNode != null || isStaticFromExample, isCoroutine, returnType, apiVersion, desc.Text, docPath); ParseParameters(eventFunction, signature, details, hintNamespace, argumentNames); return(eventFunction); }
private void ParseFile(string filename, Version apiVersion) { var document = ApiNode.Load(filename); var section = document?.SelectOne(@"//div.content/div.section"); var header = section?.SelectOne(@"div.mb20.clear"); var name = header?.SelectOne(@"h1.heading.inherit"); // Type or type member name var ns = header?.SelectOne(@"p"); // "class in {ns}" // Only interested in types at this point if (name == null || ns == null) { return; } // Only types that have messages var messages = section.Subsection("Messages").ToArray(); if (messages.Length == 0) { return; } var match = NsRegex.Match(ns.Text); var clsType = match.Groups["type"].Value; var nsName = match.Groups["namespace"].Value; var unityApiType = api.AddType(nsName, name.Text, clsType, filename, apiVersion); foreach (var message in messages) { var eventFunction = ParseMessage(message, apiVersion, nsName); unityApiType.MergeEventFunction(eventFunction, apiVersion); } }
private void ParseFile([NotNull] string filename) { var document = ApiNode.Load(filename); var section = document?.SelectOne(@"//div.content/div.section"); var header = section?.SelectOne(@"div.mb20.clear"); var cls = header?.SelectOne(@"h1.heading.inherit"); var ns = header?.SelectOne(@"p"); if (cls == null || ns == null) { return; } var messages = section.Subsection("Messages").ToArray(); if (messages.Length == 0) { return; } api.Enter("type"); var clsType = NsRegex.Replace(ns.Text, "$1"); api.SetAttribute("kind", clsType); api.SetAttribute("name", cls.Text); var nsName = NsRegex.Replace(ns.Text, "$2"); api.SetAttribute(@"ns", nsName); var hostType = new ApiType(string.Concat(nsName, ".", cls.Text)); api.SetAttribute("path", new Uri(filename).AbsoluteUri); foreach (var message in messages) { string detailsPath; ApiType type; if (!ParseMessage(message, out detailsPath, out type)) { continue; } api.LeaveTo("message"); api.SetAttribute("path", new Uri(detailsPath).AbsoluteUri); api.Enter("returns"); api.SetAttribute("type", type.FullName); api.SetAttribute("array", type.IsArray); } }
private UnityApiEventFunction ParseMessage(string className, ApiNode message, Version apiVersion, string hintNamespace, HashSet <string> processed) { var link = message.SelectOne(@"td.lbl/a"); var desc = message.SelectOne(@"td.desc"); if (link == null || desc == null) { return(null); } var detailsPath = link[@"href"]; if (string.IsNullOrWhiteSpace(detailsPath)) { return(null); } var scriptReferenceRelativePath = Directory.Exists(ScriptReferenceRelativePath1) ? ScriptReferenceRelativePath1 : ScriptReferenceRelativePath2; var path = Path.Combine(scriptReferenceRelativePath, detailsPath); processed.Add(path); if (!File.Exists(path)) { return(null); } var detailsDoc = ApiNode.Load(path); var details = detailsDoc?.SelectOne(@"//div.content/div.section"); var signature = details?.SelectOne(@"div.mb20.clear/h1.heading.inherit"); var staticNode = details?.SelectOne(@"div.subsection/p/code.varname[text()='static']"); if (signature == null) { return(null); } var isCoroutine = IsCoroutineRegex.IsMatch(details.Text); var messageName = link.Text; var returnType = ApiType.Void; var argumentNames = EmptyArray <string> .Instance; var isStaticFromExample = false; var examples = PickExample(details); if (examples.Length > 0) { var tuple = ParseDetailsFromExample(messageName, examples, hintNamespace); // As of 2017.4, the docs for MonoBehaviour.OnCollisionEnter2D don't include a valid example. It demonstrates // OnTriggerEnter2D instead. Similar problems for these other methods if (tuple == null) { var fullName = $"{className}.{messageName}"; switch (fullName) { case "MonoBehaviour.OnCollisionEnter2D": case "MonoBehaviour.OnCollisionExit2D": case "MonoBehaviour.OnCollisionStay2D": case "MonoBehaviour.Start": case "MonoBehaviour.OnDestroy": Console.WriteLine( $"WARNING: Unable to parse example for {fullName}. Example incorrect in docs"); break; // case "Network.OnDisconnectedFromServer": // Bug in 2018.2 documentation // Console.WriteLine($"WARNING: Missing example for {fullName}"); // break; default: foreach (var example in examples) { Console.WriteLine(example.Text); Console.WriteLine(); } throw new InvalidOperationException($"Failed to parse example for {className}.{messageName}"); } } if (tuple != null) { returnType = tuple.Item1; argumentNames = tuple.Item2; isStaticFromExample = tuple.Item3; } } if (Equals(returnType, ApiType.IEnumerator)) { returnType = ApiType.Void; isCoroutine = true; } var docPath = Path.Combine(scriptReferenceRelativePath, detailsPath); var eventFunction = new UnityApiEventFunction(messageName, staticNode != null || isStaticFromExample, isCoroutine, returnType, apiVersion, desc.Text, docPath); ParseParameters(eventFunction, signature, details, hintNamespace, argumentNames); return(eventFunction); }
private bool ParseMessage([NotNull] ApiNode message, out string path, out ApiType type) { path = string.Empty; type = new ApiType("void"); var link = message.SelectOne(@"td.lbl/a"); var desc = message.SelectOne(@"td.desc"); if (link == null || desc == null) { return(false); } var detailsPath = link[@"href"]; if (string.IsNullOrWhiteSpace(detailsPath)) { return(false); } path = Path.Combine(rootPath, detailsPath); if (!File.Exists(path)) { return(false); } var detailsDoc = ApiNode.Load(path); var details = detailsDoc?.SelectOne(@"//div.content/div.section"); var signature = details?.SelectOne(@"div.mb20.clear/h1.heading.inherit"); var staticNode = details?.SelectOne(@"div.subsection/p/code.varname[text()='static']"); if (signature == null) { return(false); } api.Enter("message"); api.SetAttribute("name", link.Text); api.SetAttribute("static", staticNode != null); var description = desc.Text; if (!string.IsNullOrWhiteSpace(description)) { api.SetAttribute("description", description); } // E.g. OnCollisionExit2D(Collision2D) var argumentString = SigRegex.Replace(signature.Text, "$2$3"); if (string.IsNullOrWhiteSpace(argumentString)) { return(true); } var argumentStrings = argumentString.Split(',') .Select(s => s.Trim()) .ToArray(); var total = argumentStrings.Length; var arguments = argumentStrings.Select((s, i) => new Argument(s, i, total)).ToArray(); ResolveArguments(link.Text, details, arguments, ref type); api.Enter("parameters"); foreach (var argument in arguments) { api.Enter("parameter"); api.SetAttribute("type", argument.Type.FullName); api.SetAttribute("array", argument.Type.IsArray); api.SetAttribute("name", argument.Name); if (!string.IsNullOrWhiteSpace(argument.Description)) { api.SetAttribute("description", argument.Description); } } return(true); }