public UnityApiParameter AddParameter(string name, ApiType type, string description = null) { var parmaeter = new UnityApiParameter(name, type, description); myParameters.Add(parmaeter); return(parmaeter); }
public void Update(UnityApiParameter newParameter, string functionName) { // E.g. 2018.2 removed a UnityScript example for AssetProcessor.OnPostprocessSprites, so newer docs don't // have the proper parameter name. If the old one does, keep it. if (Name != newParameter.Name && !string.IsNullOrEmpty(newParameter.Name) && !newParameter.Name.StartsWith("arg")) { Name = newParameter.Name; } if (myDescription != newParameter.myDescription && !string.IsNullOrEmpty(newParameter.myDescription)) { myDescription = newParameter.myDescription; } if (Type.FullName != newParameter.Type.FullName) { throw new InvalidOperationException($"Parameter type differences for parameter {Name}! {Type.FullName} {newParameter.Type.FullName}"); } if (Type.IsArray != newParameter.Type.IsArray || Type.IsByRef != newParameter.Type.IsByRef) { Console.WriteLine("WARNING: Parameter `{2}` of function `{3}` type changed: was {0} now {1}", Type, newParameter.Type, Name, functionName); Type = newParameter.Type; } }
public UnityApiParameter(string name, ApiType type, string description) { Name = name; myType = type; myDescription = description; myJustification = string.Empty; }
// Gets return type and argument names from example private static Tuple <ApiType, string[], bool> ParseDetailsFromExample(string messageName, ApiNode example, string owningMessageNamespace) { var blankCleanup1 = new Regex(@"\s+"); var blankCleanup2 = new Regex(@"\s*(\W)\s*"); var arrayFixup = new Regex(@"(\[\])(\w)"); var exampleText = example.Text; exampleText = blankCleanup1.Replace(exampleText, " "); exampleText = blankCleanup2.Replace(exampleText, "$1"); exampleText = arrayFixup.Replace(exampleText, "$1 $2"); var jsRegex = new Regex($@"(?:\W|^)(?<static>static\s+)?function {messageName}\((?<parameters>[^)]*)\)(?::(?<returnType>\w+\W*))?\{{"); var m = jsRegex.Match(exampleText); if (m.Success) { var returnType = new ApiType(m.Groups["returnType"].Value, owningMessageNamespace); var parameters = m.Groups["parameters"].Value.Split(','); var isStatic = m.Groups["static"].Success; var arguments = new string[parameters.Length]; for (var i = 0; i < parameters.Length; ++i) { arguments[i] = parameters[i].Split(':')[0]; } return(Tuple.Create(returnType, arguments, isStatic)); } var csRegex = new Regex($@"(?:\W|^)(?<static>static\s+)?(?<returnType>\w+\W*) {messageName}\((?<parameters>[^)]*)\)"); m = csRegex.Match(exampleText); if (m.Success) { var nameRegex = new Regex(@"^.*?\W(\w+)$"); var returnType = new ApiType(m.Groups["returnType"].Value, owningMessageNamespace); var parameters = m.Groups["parameters"].Value.Split(','); var isStatic = m.Groups["static"].Success; var arguments = new string[parameters.Length]; for (var i = 0; i < parameters.Length; ++i) { arguments[i] = nameRegex.Replace(parameters[i], "$1"); } return(Tuple.Create(returnType, arguments, isStatic)); } return(null); }
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 static Tuple <ApiType, string[], bool> ParseDetailsFromExample(string messageName, ApiNode example, string owningMessageNamespace) { // Grr. This took far too long to figure out... // The example for OnProjectChange uses "OnProjectChanged" instead // https://docs.unity3d.com/ScriptReference/EditorWindow.OnProjectChange.html if (messageName == "OnProjectChange" && example.Text.Contains("OnProjectChanged")) { messageName = "OnProjectChanged"; } var exampleText = example.Text; exampleText = SingleLineCommentsRegex.Replace(exampleText, string.Empty); exampleText = BlankCleanup1.Replace(exampleText, " "); exampleText = BlankCleanup2.Replace(exampleText, "$1"); exampleText = ArrayFixup.Replace(exampleText, "$1 $2"); // This matches both C# and JS function signatures var functionRegex = new Regex($@"(?:\W|^)(?<static>static\s+)?(?<returnType>\w+\W*)\s+{messageName}\((?<parameters>[^)]*)\)(?::(?<returnType>\w+\W*))?{{"); var m = functionRegex.Match(exampleText); if (m.Success) { var returnTypeName = m.Groups["returnType"].Value; if (returnTypeName == "function") // JS without an explicit return type { returnTypeName = "void"; } var returnType = new ApiType(returnTypeName, owningMessageNamespace); var parameters = m.Groups["parameters"].Value .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var isStatic = m.Groups["static"].Success; var arguments = new string[parameters.Length]; for (var i = 0; i < parameters.Length; ++i) { if (parameters[i].Contains(":")) { arguments[i] = parameters[i].Split(':')[0]; } else { arguments[i] = ParameterNameRegex.Replace(parameters[i], "$1"); } } return(Tuple.Create(returnType, arguments, isStatic)); } return(null); }
public UnityApiEventFunction(string name, bool isStatic, ApiType returnType, Version apiVersion, string description = null, string docPath = null, bool undocumented = false) { Name = name; myIsStatic = isStatic; myDescription = description; myDocPath = docPath; myUndocumented = undocumented; myReturnType = returnType; UpdateSupportedVersion(apiVersion); myParameters = new List <UnityApiParameter>(); }
public Argument([NotNull] string type, int index, int total) { Name = total > 1 ? $"arg{index + 1}" : @"arg"; if (type.Contains(' ')) { var parts = type.Split(' '); Type = new ApiType(parts[0]); Name = parts[1]; } else { Type = new ApiType(type); } }
// Gets return type and argument names from example private static Tuple <ApiType, string[]> ParseDetailsFromExample(string messageName, ApiNode example, string owningMessageNamespace) { var blankCleanup1 = new Regex(@"\s+"); var blankCleanup2 = new Regex(@"\s*(\W)\s*"); var exampleText = example.Text; exampleText = blankCleanup1.Replace(exampleText, " "); exampleText = blankCleanup2.Replace(exampleText, "$1"); var jsRegex = new Regex($@"(?:\W|^)function {messageName}\(([^)]*)\)(?::(\w+))?\{{"); var m = jsRegex.Match(exampleText); if (m.Success) { var returnType = new ApiType(m.Groups[2].Value, owningMessageNamespace); var parameters = m.Groups[1].Value.Split(','); var arguments = new string[parameters.Length]; for (var i = 0; i < parameters.Length; ++i) { arguments[i] = parameters[i].Split(':')[0]; } return(Tuple.Create(returnType, arguments)); } var csRegex = new Regex($@"(\w+) {messageName}\(([^)]*)\)"); m = csRegex.Match(exampleText); if (m.Success) { var nameRegex = new Regex(@"\W(\w+)$"); var returnType = new ApiType(m.Groups[1].Value, owningMessageNamespace); var parameters = m.Groups[2].Value.Split(','); var arguments = new string[parameters.Length]; for (var i = 0; i < parameters.Length; ++i) { arguments[i] = nameRegex.Replace(parameters[i], "$1"); } return(Tuple.Create(returnType, arguments)); } return(null); }
private static void ParseMessageExample(string messageName, IReadOnlyList <Argument> arguments, ApiNode example, ref ApiType type) { var blankCleanup1 = new Regex(@"\s+"); var blankCleanup2 = new Regex(@"\s*(\W)\s*"); var exampleText = example.Text; exampleText = blankCleanup1.Replace(exampleText, " "); exampleText = blankCleanup2.Replace(exampleText, "$1"); var jsRegex = new Regex($@"(?:\W|^)function {messageName}\(([^)]*)\)(?::(\w+))?\{{"); var m = jsRegex.Match(exampleText); if (m.Success) { type = new ApiType(m.Groups[2].Value); var parameters = m.Groups[1].Value.Split(','); for (var i = 0; i < arguments.Count; ++i) { arguments[i].Name = parameters[i].Split(':')[0]; } return; } var csRegex = new Regex($@"(\w+) {messageName}\(([^)]*)\)"); m = csRegex.Match(exampleText); if (m.Success) { var nameRegex = new Regex(@"\W(\w+)$"); type = new ApiType(m.Groups[1].Value); var parameters = m.Groups[2].Value.Split(','); for (var i = 0; i < arguments.Count; ++i) { arguments[i].Name = nameRegex.Replace(parameters[i], "$1"); } return; } Console.WriteLine(exampleText); }
public UnityApiEventFunction(string name, bool isStatic, bool isCoroutine, ApiType returnType, Version apiVersion, string description = null, string docPath = null, bool undocumented = false) { Name = name; myIsStatic = isStatic; myIsCoroutine = isCoroutine; myDescription = description; if (myDescription?.StartsWith(":ref::") == true) // Yes, really. MonoBehaviour.OnCollisionStay in 2018.1 { myDescription = myDescription.Substring(6); } myDocPath = docPath; myUndocumented = undocumented; myReturnType = returnType; UpdateSupportedVersion(apiVersion); myParameters = new List <UnityApiParameter>(); }
public static UnityApiParameter ImportFrom(XElement parameter) { var typeName = parameter.Attribute("type").Value; var isArray = bool.Parse(parameter.Attribute("array").Value); var byRefAttribute = parameter.Attribute("byRef"); var isByRef = byRefAttribute != null && bool.Parse(byRefAttribute.Value); var name = parameter.Attribute("name").Value; var justification = parameter.Attribute("justification")?.Value; var isOptional = justification != null && bool.Parse(parameter.Attribute("optional").Value); var description = parameter.Attribute("description")?.Value; var apiType = new ApiType(typeName + (isArray ? "[]" : string.Empty) + (isByRef ? "&" : string.Empty)); var p = new UnityApiParameter(name, apiType, description); if (isOptional) { p.SetOptional(justification); } return(p); }
public void Update(UnityApiParameter newParameter, string functionName) { if (Name != newParameter.Name && !string.IsNullOrEmpty(newParameter.Name)) { Name = newParameter.Name; } if (myDescription != newParameter.myDescription && !string.IsNullOrEmpty(newParameter.myDescription)) { myDescription = newParameter.myDescription; } if (myType.FullName != newParameter.myType.FullName) { throw new InvalidOperationException($"Parameter type differences for parameter {Name}! {myType.FullName} {newParameter.myType.FullName}"); } if (myType.IsArray != newParameter.myType.IsArray || myType.IsByRef != newParameter.myType.IsByRef) { Console.WriteLine("WARNING: Parameter `{2}` of function `{3}` type changed: was {0} now {1}", myType, newParameter.myType, Name, functionName); myType = newParameter.myType; } }
public static UnityApiEventFunction ImportFrom(XElement message, HasVersionRange versions) { var name = message.Attribute("name").Value; var isStatic = bool.Parse(message.Attribute("static").Value); var coroutineAttribute = message.Attribute("coroutine"); var isCoroutine = coroutineAttribute != null && bool.Parse(coroutineAttribute.Value); var description = message.Attribute("description")?.Value; var path = message.Attribute("path")?.Value; var undocumentedAttribute = message.Attribute("undocumented"); var isUndocumented = undocumentedAttribute != null && bool.Parse(undocumentedAttribute.Value); var returns = message.Descendants("returns").First(); var type = returns.Attribute("type").Value; var isArray = bool.Parse(returns.Attribute("array").Value); var returnType = new ApiType(type + (isArray ? "[]" : string.Empty)); var function = new UnityApiEventFunction(name, isStatic, isCoroutine, returnType, new Version(int.MaxValue, 0), description, path, isUndocumented); function.ImportVersionRange(message, versions); foreach (var parameter in message.Descendants("parameter")) { function.myParameters.Add(UnityApiParameter.ImportFrom(parameter)); } return(function); }
protected bool Equals(ApiType other) { return(string.Equals(FullName, other.FullName) && IsArray == other.IsArray && IsByRef == other.IsByRef); }
public UnityApiParameter(string name, ApiType type, string description) { myName = name; myType = type; myDescription = description; }
public void SetReturnType(ApiType returnType) { myReturnType = returnType; }
private static void ResolveArguments([NotNull] string message, [NotNull] ApiNode details, [NotNull] IReadOnlyList <Argument> arguments, [NotNull] ref ApiType type) { var parameters = details.Subsection("Parameters").ToArray(); if (parameters.Any()) { ParseMessageParameters(arguments, parameters); return; } var example = PickExample(details); if (example == null) { return; } ParseMessageExample(message, arguments, example, ref type); }
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); }
public Argument(ApiType type, string name) { Name = name; Type = type; }