Example #1
0
        private HashSet <IDeclaration> FindHotRootMethods([NotNull] ICSharpFile file, [NotNull] IPsiSourceFile sourceFile)
        {
            var api    = file.GetSolution().GetComponent <UnityApi>();
            var result = new HashSet <IDeclaration>();

            var descendantsEnumerator = file.Descendants();

            while (descendantsEnumerator.MoveNext())
            {
                switch (descendantsEnumerator.Current)
                {
                case IClassLikeDeclaration classLikeDeclaration:
                    var declaredSymbol = classLikeDeclaration.DeclaredElement;
                    if (declaredSymbol == null ||
                        !declaredSymbol.GetAllSuperTypes().Any(t => t.GetClrName().Equals(KnownTypes.MonoBehaviour)))
                    {
                        descendantsEnumerator.SkipThisNode();
                    }

                    break;

                case IMethodDeclaration methodDeclaration:
                    // check that method is hot and add it to container
                    var declaredElement = methodDeclaration.DeclaredElement;
                    if (declaredElement == null)
                    {
                        break;
                    }
                    var name = declaredElement.ShortName;
                    if (ourKnownHotMonoBehaviourMethods.Contains(name) && api.IsEventFunction(declaredElement))
                    {
                        result.Add(methodDeclaration);
                    }
                    break;

                case IInvocationExpression invocationExpression:
                    // we should find 'StartCoroutine' method, because passed symbol will be hot too
                    var reference = (invocationExpression.InvokedExpression as IReferenceExpression)?.Reference;
                    if (reference == null)
                    {
                        break;
                    }

                    var info = reference.Resolve();
                    if (info.ResolveErrorType != ResolveErrorType.OK)
                    {
                        break;
                    }

                    declaredElement = info.DeclaredElement as IMethod;
                    if (declaredElement == null)
                    {
                        break;
                    }

                    var containingType = declaredElement.GetContainingType();

                    if (containingType == null || containingType.GetClrName().Equals(KnownTypes.MonoBehaviour) &&
                        declaredElement.ShortName.Equals("StartCoroutine"))
                    {
                        var arguments = invocationExpression.Arguments;
                        if (arguments.Count == 0 || arguments.Count > 2)
                        {
                            break;
                        }

                        var firstArgument = arguments[0].Value;
                        if (firstArgument == null)
                        {
                            break;
                        }

                        var coroutineMethodDeclaration = ExtractMethodDeclarationFromStartCoroutine(firstArgument);
                        if (coroutineMethodDeclaration == null)
                        {
                            break;
                        }

                        var declarations = coroutineMethodDeclaration.GetDeclarationsIn(sourceFile).Where(t => t.GetSourceFile() == sourceFile);
                        foreach (var declaration in declarations)
                        {
                            result.Add(declaration);
                        }
                    }

                    break;
                }
            }

            return(result);
        }