public ReferenceCollection GetReferences(ITreeNode element, ReferenceCollection oldReferences)
        {
            if (ResolveUtil.CheckThatAllReferencesBelongToElement <MonoScriptReference>(oldReferences, element))
            {
                return(oldReferences);
            }

            if (!(element is IPlainScalarNode guidValue))
            {
                return(ReferenceCollection.Empty);
            }

            // m_Script: {fileID: 11500000, guid: xxx, type: x}
            var guidEntry         = FlowMapEntryNavigator.GetByValue(guidValue);
            var flowIDMap         = FlowMappingNodeNavigator.GetByEntrie(guidEntry);
            var blockMappingEntry = BlockMappingEntryNavigator.GetByValue(flowIDMap);

            if (guidEntry?.Key.MatchesPlainScalarText("guid") == true &&
                blockMappingEntry?.Key.MatchesPlainScalarText("m_Script") == true)
            {
                var fileID = flowIDMap.AsFileID();
                if (fileID != null && !fileID.IsNullReference && fileID.IsMonoScript)
                {
                    var metaGuidCache = element.GetSolution().GetComponent <MetaFileGuidCache>();
                    var reference     = new MonoScriptReference(guidValue, fileID, metaGuidCache);
                    return(new ReferenceCollection(reference));
                }
            }

            return(ReferenceCollection.Empty);
        }
Пример #2
0
        public ReferenceCollection GetReferences(ITreeNode element, ReferenceCollection oldReferences)
        {
            if (ResolveUtil.CheckThatAllReferencesBelongToElement <UnityEventTargetReference>(oldReferences, element))
            {
                return(oldReferences);
            }

            if (!(element is IPlainScalarNode methodNameValue))
            {
                return(ReferenceCollection.Empty);
            }

            // E.g. element is the m_MethodName scalar value "ButtonClickedHandler" in this structure:
            // m_OnClick:
            //   m_PersistentCalls:
            //     m_Calls:
            //     - m_Target: {fileID: 1870695363}
            //       m_MethodName: ButtonClickedHandler
            //       m_Mode: 3
            //       m_Arguments:
            //         m_ObjectArgument: {fileID: 0}
            //         m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
            //         m_IntArgument: 1
            //         m_FloatArgument: 0
            //         m_StringArgument:
            //         m_BoolArgument: 0
            //       m_CallState: 2
            //   m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0,
            //     Culture=neutral, PublicKeyToken=null
            var methodNameMapEntry = BlockMappingEntryNavigator.GetByValue(methodNameValue);
            var callMapNode        = BlockMappingNodeNavigator.GetByEntrie(methodNameMapEntry);
            var callsSequenceEntry = SequenceEntryNavigator.GetByValue(callMapNode);
            var callsSequenceNode  = BlockSequenceNodeNavigator.GetByEntrie(callsSequenceEntry);
            var callsMapEntry      = BlockMappingEntryNavigator.GetByValue(callsSequenceNode);

            // callsMapEntry should be "m_Calls" (and contain a value that is a sequence node). If it's not null,
            // everything else is also not null
            if (callsMapEntry == null)
            {
                return(ReferenceCollection.Empty);
            }

            if (methodNameMapEntry.Key.MatchesPlainScalarText("m_MethodName") &&
                callsMapEntry.Key.MatchesPlainScalarText("m_Calls"))
            {
                // If we have a guid, that means this event handler exists inside another asset. That asset might be
                // a .dll, in which case we don't want to add a reference (the primary purpose of these references
                // is to enable Find Usages of methods, not navigation *from* YAML). Or it might be e.g. a prefab.
                // This would be a reference to a prefab that contains a MonoScript asset that has the method
                // TODO: Create an index of other assets that we could target
                var fileID = callMapNode.FindMapEntryBySimpleKey("m_Target")?.Value.AsFileID();
                if (fileID != null && !fileID.IsNullReference && fileID.guid == null)
                {
                    var reference = new UnityEventTargetReference(methodNameValue, fileID);
                    return(new ReferenceCollection(reference));
                }
            }

            return(ReferenceCollection.Empty);
        }
Пример #3
0
        public override ReferenceCollection GetReferences(ITreeNode element, ReferenceCollection oldReferences)
        {
            if (ResolveUtil.CheckThatAllReferencesBelongToElement <UnityEventFunctionReference>(oldReferences, element))
            {
                return(oldReferences);
            }

            var literal = GetValidStringLiteralExpression(element);

            if (literal == null)
            {
                return(ReferenceCollection.Empty);
            }

            if (!IsFirstArgumentInMethod(literal))
            {
                return(ReferenceCollection.Empty);
            }

            var invocationExpression = literal.GetContainingNode <IInvocationExpression>();
            var invocationReference  = invocationExpression?.Reference;
            var invokedMethod        = invocationReference?.Resolve().DeclaredElement as IMethod;

            if (invokedMethod == null)
            {
                return(ReferenceCollection.Empty);
            }

            var isInvokedFunction = ourInvokeMethodNames.Contains(invokedMethod.ShortName);
            var isCoroutine       = IsCoroutine(invokedMethod);

            if (isInvokedFunction || isCoroutine)
            {
                var containingType = invokedMethod.GetContainingType();
                if (containingType != null && Equals(containingType.GetClrName(), KnownTypes.MonoBehaviour))
                {
                    var targetType = invocationExpression.ExtensionQualifier?.GetExpressionType()
                                     .ToIType()?.GetTypeElement()
                                     ??
                                     literal.GetContainingNode <IMethodDeclaration>()?
                                     .DeclaredElement?.GetContainingType();

                    if (targetType != null)
                    {
                        var methodSignature = GetMethodSignature(invocationExpression, invokedMethod, isCoroutine);
                        var reference       = new UnityEventFunctionReference(targetType, literal, methodSignature);
                        return(new ReferenceCollection(reference));
                    }
                }
            }

            return(ReferenceCollection.Empty);
        }
Пример #4
0
        public ReferenceCollection GetReferences(ITreeNode element, ReferenceCollection oldReferences)
        {
            if (ResolveUtil.CheckThatAllReferencesBelongToElement <AsmDefNameReference>(oldReferences, element))
            {
                return(oldReferences);
            }

            if (element.IsReferencesStringLiteralValue())
            {
                return(new ReferenceCollection(new AsmDefNameReference((IJavaScriptLiteralExpression)element)));
            }

            return(ReferenceCollection.Empty);
        }
        public virtual IReference[] GetReferences(ITreeNode element, IReference[] oldReferences)
        {
            if (ResolveUtil.CheckThatAllReferencesBelongToElement <IRazorReference>(oldReferences, element))
            {
                return(oldReferences);
            }
            if (!IsAppropriateNode(element))
            {
                return(EmptyArray <IReference> .Instance);
            }

            IExpression annotatedSectionExpression = razorServices.GetAnnotatedLiteralExpression(element, RazorSectionExternalAttributeName, assignmentChecker);

            if (annotatedSectionExpression is TLiteralExpression && annotatedSectionExpression.ConstantValue.IsString())
            {
                return(new IReference[]
                {
                    new RazorSectionDeclarationReference <TLiteralExpression>(annotatedSectionExpression)
                });
            }

            IExpression annotatedLiteralExpression = razorServices.GetAnnotatedLiteralExpression(element, RazorLayoutExternalAttributeName, assignmentChecker);

            if (annotatedLiteralExpression == null || !annotatedLiteralExpression.ConstantValue.IsString())
            {
                return(EmptyArray <IReference> .Instance);
            }

            IPsiSourceFile sourceFile = element.GetDocumentRange()
                                        .Document.IfNotNull(_ => _.GetPsiSourceFiles(solution),
                                                            EmptyList <IPsiSourceFile> .InstanceList)
                                        .Concat(element.GetSourceFile())
                                        .WhereNotNull()
                                        .FirstOrDefault();

            FileSystemPath location      = sourceFile.GetLocation();
            PathQualifier  pathQualifier = (!location.IsEmpty) ? new PathQualifier(solution, location.Directory) : null;

            return(new IReference[]
            {
                new NancyRazorLayoutReference <ITreeNode>(annotatedLiteralExpression, pathQualifier,
                                                          annotatedLiteralExpression,
                                                          TreeTextRange.FromLength(annotatedLiteralExpression.GetTextLength()),
                                                          sourceFile.IfNotNull(_ => _.LanguageType), true, true)
            });
        }
Пример #6
0
        public override ReferenceCollection GetReferences(ITreeNode element, ReferenceCollection oldReferences)
        {
            if (ResolveUtil.CheckThatAllReferencesBelongToElement <SyncVarHookReference>(oldReferences, element))
            {
                return(oldReferences);
            }

            var literal = element as ILiteralExpression;

            if (literal == null || !literal.ConstantValue.IsString())
            {
                return(ReferenceCollection.Empty);
            }

            var propertyAssignment          = literal.GetContainingNode <IPropertyAssignment>();
            var propertyAssignmentReference = propertyAssignment?.Reference;

            if (propertyAssignmentReference == null || propertyAssignmentReference.GetName() != "hook")
            {
                return(ReferenceCollection.Empty);
            }

            var assignedField = propertyAssignmentReference.Resolve().DeclaredElement as IField;
            var attributeType = assignedField?.GetContainingType();

            if (attributeType == null || !Equals(attributeType.GetClrName(), KnownTypes.SyncVarAttribute))
            {
                return(ReferenceCollection.Empty);
            }

            var multipleFieldDeclaration = propertyAssignment.GetContainingNode <IMultipleFieldDeclaration>();
            var declaredFieldTypeUsage   = multipleFieldDeclaration?.TypeUsage;
            var containingType           = multipleFieldDeclaration?.GetContainingNode <IClassLikeDeclaration>()?.DeclaredElement;

            if (containingType != null && declaredFieldTypeUsage != null)
            {
                var declaredFieldType = CSharpTypeFactory.CreateType(declaredFieldTypeUsage);
                var reference         = new SyncVarHookReference(containingType, declaredFieldType, literal);
                return(new ReferenceCollection(reference));
            }

            return(ReferenceCollection.Empty);
        }
        public ReferenceCollection GetReferences(ITreeNode element, ReferenceCollection oldReferences)
        {
            if (ResolveUtil.CheckThatAllReferencesBelongToElement <UnityEventTargetReference>(oldReferences, element))
            {
                return(oldReferences);
            }

            if (!(element is IPlainScalarNode methodNameValue))
            {
                return(ReferenceCollection.Empty);
            }

            // E.g. element is the m_MethodName scalar value "ButtonClickedHandler" in this structure:
            // m_OnClick:
            //   m_PersistentCalls:
            //     m_Calls:
            //     - m_Target: {fileID: 1870695363}
            //       m_MethodName: ButtonClickedHandler
            //       m_Mode: 3
            //       m_Arguments:
            //         m_ObjectArgument: {fileID: 0}
            //         m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
            //         m_IntArgument: 1
            //         m_FloatArgument: 0
            //         m_StringArgument:
            //         m_BoolArgument: 0
            //       m_CallState: 2
            //   m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0,
            //     Culture=neutral, PublicKeyToken=null
            var methodNameMapEntry = BlockMappingEntryNavigator.GetByContent(ContentNodeNavigator.GetByValue(methodNameValue));
            var callMapNode        = BlockMappingNodeNavigator.GetByEntrie(methodNameMapEntry);
            var callsSequenceEntry = SequenceEntryNavigator.GetByValue(callMapNode);
            var callsSequenceNode  = BlockSequenceNodeNavigator.GetByEntrie(callsSequenceEntry);
            var callsMapEntry      = BlockMappingEntryNavigator.GetByContent(ContentNodeNavigator.GetByValue(callsSequenceNode));

            // callsMapEntry should be "m_Calls" (and contain a value that is a sequence node). If it's not null,
            // everything else is also not null
            if (callsMapEntry == null)
            {
                return(ReferenceCollection.Empty);
            }

            if (methodNameMapEntry.Key.MatchesPlainScalarText("m_MethodName") &&
                callsMapEntry.Key.MatchesPlainScalarText("m_Calls"))
            {
                var fileID = callMapNode.FindMapEntryBySimpleKey("m_Target")?.Content.Value.AsFileID();
                if (fileID != null && !fileID.IsNullReference)
                {
                    var text = callMapNode.Entries.FirstOrDefault(t => t.Key.MatchesPlainScalarText("m_Mode"))?.Content.Value
                               .GetPlainScalarText();

                    var argMode = EventHandlerArgumentMode.Unknown;
                    if (int.TryParse(text, out var mode))
                    {
                        if (1 <= mode && mode <= 6)
                        {
                            argMode = (EventHandlerArgumentMode)mode;
                        }
                    }

                    var arguments      = callMapNode.Entries.FirstOrDefault(t => t.Key.MatchesPlainScalarText("m_Arguments"))?.Content.Value as IBlockMappingNode;
                    var typeNameRecord = arguments?.Entries.FirstOrDefault(t => t.Key.MatchesPlainScalarText("m_ObjectArgumentAssemblyTypeName"))?.Content.Value;
                    var type           = typeNameRecord?.GetPlainScalarText()?.Split(',').FirstOrDefault();
                    if (type.IsNullOrEmpty() && mode == 1)
                    {
                        type = null;
                    }

                    var reference = new UnityEventTargetReference(methodNameValue, argMode, type, fileID);
                    return(new ReferenceCollection(reference));
                }
            }

            return(ReferenceCollection.Empty);
        }
Пример #8
0
        public ReferenceCollection GetReferences(ITreeNode element, ReferenceCollection oldReferences)
        {
            if (ResolveUtil.CheckThatAllReferencesBelongToElement <UnityEventTargetReference>(oldReferences, element))
            {
                return(oldReferences);
            }

            if (!(element is IPlainScalarNode methodNameValue))
            {
                return(ReferenceCollection.Empty);
            }

            // E.g. element is the m_MethodName scalar value "ButtonClickedHandler" in this structure:
            // m_OnClick:
            //   m_PersistentCalls:
            //     m_Calls:
            //     - m_Target: {fileID: 1870695363}
            //       m_MethodName: ButtonClickedHandler
            //       m_Mode: 3
            //       m_Arguments:
            //         m_ObjectArgument: {fileID: 0}
            //         m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
            //         m_IntArgument: 1
            //         m_FloatArgument: 0
            //         m_StringArgument:
            //         m_BoolArgument: 0
            //       m_CallState: 2
            //   m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0,
            //     Culture=neutral, PublicKeyToken=null
            // Note that m_TypeName was removed in Unity 2018.4
            var methodNameMapEntry = BlockMappingEntryNavigator.GetByContent(ContentNodeNavigator.GetByValue(methodNameValue));
            var callMapNode        = BlockMappingNodeNavigator.GetByEntrie(methodNameMapEntry);
            var callsMapEntry      = BlockMappingEntryNavigator.GetByContent(
                ContentNodeNavigator.GetByValue(
                    BlockSequenceNodeNavigator.GetByEntrie(SequenceEntryNavigator.GetByValue(callMapNode))));

            // callsMapEntry should be "m_Calls" (and contain a value that is a sequence node). If it's not null,
            // everything else is also not null
            if (callsMapEntry == null)
            {
                return(ReferenceCollection.Empty);
            }

            // Get the event type name, if it's serialised. This field was removed in Unity 2018.4, but remember that
            // the serialised value will remain in the scene until it is re-saved.
            // The only way to get the type name in Unity 2018.4+ is to get the type of the event (e.g. m_OnClick). This
            // requires getting the type referenced in the m_Script serialised field, which might be in a referenced
            // assembly, and could be arbitrarily deep in a custom class.
            // The Event System has this problem, as the EventTrigger MonoBehaviour serialises a list of
            // EventTrigger.Event instances, and it's EventTrigger.Event.callback that gives us the UnityEvent derived
            // event type
            // The only way to do this would be to resolve all types and fields between m_PersistentCalls and the "root"
            // of the object, taking [FormerlySerialisedAs] into account
            var persistentCallsMapNode = BlockMappingNodeNavigator.GetByEntrie(
                BlockMappingEntryNavigator.GetByContent(
                    ContentNodeNavigator.GetByValue(BlockMappingNodeNavigator.GetByEntrie(callsMapEntry))));
            var eventTypeName = persistentCallsMapNode?.FindMapEntryBySimpleKey("m_TypeName")?.Content?.Value
                                ?.GetPlainScalarText();

            if (methodNameMapEntry.Key.MatchesPlainScalarText("m_MethodName") &&
                callsMapEntry.Key.MatchesPlainScalarText("m_Calls"))
            {
                var fileID = callMapNode.FindMapEntryBySimpleKey("m_Target")?.Content.Value.AsFileID();
                if (fileID != null && !fileID.IsNullReference)
                {
                    var modeText = callMapNode.FindMapEntryBySimpleKey("m_Mode")?.Content.Value.GetPlainScalarText();

                    var argMode = EventHandlerArgumentMode.EventDefined;
                    if (int.TryParse(modeText, out var mode))
                    {
                        if (1 <= mode && mode <= 6)
                        {
                            argMode = (EventHandlerArgumentMode)mode;
                        }
                    }

                    var arguments        = callMapNode.FindMapEntryBySimpleKey("m_Arguments")?.Content.Value as IBlockMappingNode;
                    var argumentTypeName = arguments.FindMapEntryBySimpleKey("m_ObjectArgumentAssemblyTypeName")?.Content
                                           .Value.GetPlainScalarText();
                    var type = argumentTypeName?.Split(',').FirstOrDefault();
                    if (argMode == EventHandlerArgumentMode.EventDefined)
                    {
                        type = eventTypeName?.Split(',').FirstOrDefault();
                    }
                    else if (argMode == EventHandlerArgumentMode.Void)
                    {
                        type = null;
                    }

                    var reference = new UnityEventTargetReference(methodNameValue, argMode, type, fileID);
                    return(new ReferenceCollection(reference));
                }
            }

            return(ReferenceCollection.Empty);
        }