Пример #1
0
        public UnityApiParameter AddParameter(string name, ApiType type, string description = null)
        {
            var parmaeter = new UnityApiParameter(name, type, description);

            myParameters.Add(parmaeter);
            return(parmaeter);
        }
Пример #2
0
        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;
            }
        }
Пример #3
0
 public UnityApiParameter(string name, ApiType type, string description)
 {
     Name            = name;
     myType          = type;
     myDescription   = description;
     myJustification = string.Empty;
 }
Пример #4
0
        // 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);
        }
Пример #5
0
        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);
            }
        }
Пример #6
0
        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);
        }
Пример #7
0
        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>();
        }
Пример #8
0
        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);
            }
        }
Пример #9
0
        // 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);
        }
Пример #10
0
        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);
        }
Пример #11
0
        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>();
        }
Пример #12
0
        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);
        }
Пример #13
0
        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;
            }
        }
Пример #14
0
        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);
        }
Пример #15
0
 protected bool Equals(ApiType other)
 {
     return(string.Equals(FullName, other.FullName) && IsArray == other.IsArray && IsByRef == other.IsByRef);
 }
Пример #16
0
 public UnityApiParameter(string name, ApiType type, string description)
 {
     myName        = name;
     myType        = type;
     myDescription = description;
 }
Пример #17
0
 public void SetReturnType(ApiType returnType)
 {
     myReturnType = returnType;
 }
Пример #18
0
        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);
        }
Пример #19
0
        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);
        }
Пример #20
0
 public Argument(ApiType type, string name)
 {
     Name = name;
     Type = type;
 }