protected override RichText GetDisplayName()
        {
            var richText = base.GetDisplayName();

            LookupUtil.AddEmphasize(richText, new TextRange(0, richText.Length));
            return(richText);
        }
Example #2
0
        private ILookupItem CreateMethodItem(CSharpCodeCompletionContext context,
                                             UnityEventFunction eventFunction, IClassLikeDeclaration declaration,
                                             bool hasReturnType, AccessRights accessRights,
                                             MemberGenerationContext generationContext)
        {
            if (CSharpLanguage.Instance == null)
            {
                return(null);
            }

            // Only show the modifier in the list text if it's not already specified and there isn't a return type, in
            // which case we default to `private`. E.g. if someone types `OnAnim`, then show `private void OnAnimate...`
            // but if they type `void OnAnim`, they don't want a modifier, and if they type `public void OnAnim` then
            // they want to use `public`
            var showModifier = false;

            if (!hasReturnType && accessRights == AccessRights.NONE)
            {
                showModifier = true;
                accessRights = AccessRights.PRIVATE;
            }

            // Note that we can't keep this declaration - it will become invalid as the user types to narrow down the
            // search and modifies the PSI file. This only affects ReSharper, Rider has different code completion
            // mechanism
            var factory           = CSharpElementFactory.GetInstance(declaration, false);
            var methodDeclaration = eventFunction.CreateDeclaration(factory, declaration, accessRights);

            if (methodDeclaration.DeclaredElement == null)
            {
                return(null);
            }

            // This is effectively the same as GenerateMemberPresentation, but without the overhead that comes
            // with the flexibility of formatting any time of declared element. We just hard code the format
            var predefinedType = context.PsiModule.GetPredefinedType();
            var parameters     = string.Empty;

            if (eventFunction.Parameters.Length > 0)
            {
                var sb = new StringBuilder();
                for (var i = 0; i < eventFunction.Parameters.Length; i++)
                {
                    if (i > 0)
                    {
                        sb.Append(", ");
                    }

                    var parameter = eventFunction.Parameters[i];
                    var type      = predefinedType.TryGetType(parameter.ClrTypeName, NullableAnnotation.Unknown);
                    var typeName  = type?.GetPresentableName(CSharpLanguage.Instance) ??
                                    parameter.ClrTypeName.ShortName;
                    sb.AppendFormat("{0}{1}{2}", parameter.IsByRef ? "out" : string.Empty,
                                    typeName, parameter.IsArray ? "[]" : string.Empty);
                }
                parameters = sb.ToString();
            }
            var text            = $"{eventFunction.Name}({parameters})";
            var parameterOffset = eventFunction.Name.Length;

            var modifier = showModifier
                ? CSharpDeclaredElementPresenter.Instance.Format(accessRights) + " "
                : string.Empty;

            var psiIconManager = context.BasicContext.LookupItemsOwner.Services.PsiIconManager;

            // Note that because this is a text based lookup item, then it won't be included if the normal C# method
            // filter is applied. We can't make it a method based lookup item because the DeclaredElement isn't valid in
            // this situation - it's not a real method, and a DeclaredElementInfo would try to store a pointer to it,
            // and be unable to recreate it when it's needed.
            var textualInfo = new UnityEventFunctionTextualInfo(generationContext.MemberReplaceRanges, text, text)
            {
                Ranges = context.CompletionRanges
            };

            var lookupItem = LookupItemFactory.CreateLookupItem(textualInfo)
                             .WithPresentation(item =>
            {
                var displayName = new RichText($"{modifier}{text} {{ ... }}");

                // GenerateMemberPresentation marks everything as bold, and the parameters + block syntax as not important
                var parameterStartOffset = modifier.Length + parameterOffset;
                LookupUtil.MarkAsNotImportant(displayName,
                                              TextRange.FromLength(parameterStartOffset, displayName.Length - parameterStartOffset));
                LookupUtil.AddEmphasize(displayName, new TextRange(modifier.Length, displayName.Length));

                var image = psiIconManager.GetImage(CLRDeclaredElementType.METHOD);
                psiIconManager.AttachExtensions(image, GetAccessExtensions(accessRights));
                var marker = item.Info.Ranges.CreateVisualReplaceRangeMarker();
                return(new SimplePresentation(displayName, image, marker));
            })
                             .WithBehavior(_ => new UnityEventFunctionBehavior(textualInfo, eventFunction, accessRights))
                             .WithMatcher(_ =>
                                          new ShiftedDeclaredElementMatcher(eventFunction.Name, modifier.Length, textualInfo));

            var description = GetDescription(context, methodDeclaration);

            return(new WrappedLookupItem(lookupItem, description));
        }
        private static ILookupItem CreateMethodItem(CSharpCodeCompletionContext context,
                                                    UnityEventFunction eventFunction, IClassLikeDeclaration declaration, bool addModifier)
        {
            if (CSharpLanguage.Instance == null)
            {
                return(null);
            }

            var method = eventFunction.CreateDeclaration(CSharpElementFactory.GetInstance(declaration, false), declaration);

            if (method.DeclaredElement == null)
            {
                return(null);
            }

            var instance = new DeclaredElementInstance(method.DeclaredElement);

            var declaredElementInfo = new DeclaredElementInfoWithoutParameterInfo(method.DeclaredName, instance, CSharpLanguage.Instance,
                                                                                  context.BasicContext.LookupItemsOwner, context)
            {
                Ranges = context.CompletionRanges
            };

            // This is effectively the same as GenerateMemberPresentation, but without the overhead that comes
            // with the flexibility of formatting any time of declared element. We just hard code the format
            var predefinedType = context.PsiModule.GetPredefinedType();
            var parameters     = string.Empty;

            if (eventFunction.Parameters.Length > 0)
            {
                var sb = new StringBuilder();
                for (var i = 0; i < eventFunction.Parameters.Length; i++)
                {
                    if (i > 0)
                    {
                        sb.Append(", ");
                    }

                    var parameter = eventFunction.Parameters[i];
                    var type      = predefinedType.TryGetType(parameter.ClrTypeName);
                    var typeName  = type?.GetPresentableName(CSharpLanguage.Instance) ??
                                    parameter.ClrTypeName.ShortName;
                    sb.AppendFormat("{0}{1}{2}", parameter.IsByRef ? "out" : string.Empty,
                                    typeName, parameter.IsArray ? "[]" : string.Empty);
                }
                parameters = sb.ToString();
            }
            var text            = $"{eventFunction.Name}({parameters})";
            var parameterOffset = eventFunction.Name.Length;
            var modifier        = addModifier ? "private " : string.Empty;

            var psiIconManager = context.BasicContext.LookupItemsOwner.Services.PsiIconManager;

            return(LookupItemFactory.CreateLookupItem(declaredElementInfo)
                   .WithPresentation(item =>
            {
                var displayName = new RichText($"{modifier}{text} {{ ... }}");

                // GenerateMemberPresentation marks everything as bold, and the parameters + block syntax as not important
                var parameterStartOffset = modifier.Length + parameterOffset;
                LookupUtil.MarkAsNotImportant(displayName,
                                              TextRange.FromLength(parameterStartOffset, displayName.Length - parameterStartOffset));
                LookupUtil.AddEmphasize(displayName, new TextRange(modifier.Length, displayName.Length));

                var image = psiIconManager.GetImage(CLRDeclaredElementType.METHOD, PsiIconExtension.Private);
                var marker = item.Info.Ranges.CreateVisualReplaceRangeMarker();
                return new SimplePresentation(displayName, image, marker);
            })
                   .WithBehavior(_ => new UnityEventFunctionBehavior(declaredElementInfo, eventFunction))
                   .WithMatcher(_ =>
                                new ShiftedDeclaredElementMatcher(text, modifier.Length, declaredElementInfo,
                                                                  context.BasicContext.IdentifierMatchingStyle)));
        }
Example #4
0
        private ILookupItem CreateMethodItem(CSharpCodeCompletionContext context,
                                             UnityEventFunction eventFunction, IClassLikeDeclaration declaration,
                                             bool hasReturnType, AccessRights accessRights)
        {
            if (CSharpLanguage.Instance == null)
            {
                return(null);
            }

            // Only show the modifier in the list text if it's not already specified and there isn't a return type, in
            // which case we default to `private`. E.g. if someone types `OnAnim`, then show `private void OnAnimate...`
            // but if they type `void OnAnim`, they don't want a modifier, and if they type `public void OnAnim` then
            // they want to use `public`
            var showModifier = false;

            if (!hasReturnType && accessRights == AccessRights.NONE)
            {
                showModifier = true;
                accessRights = AccessRights.PRIVATE;
            }

            var factory           = CSharpElementFactory.GetInstance(declaration, false);
            var methodDeclaration = eventFunction.CreateDeclaration(factory, declaration, accessRights);

            if (methodDeclaration.DeclaredElement == null)
            {
                return(null);
            }

            var instance = new DeclaredElementInstance(methodDeclaration.DeclaredElement);

            var declaredElementInfo = new DeclaredElementInfoWithoutParameterInfo(methodDeclaration.DeclaredName,
                                                                                  instance, CSharpLanguage.Instance, context.BasicContext.LookupItemsOwner, context)
            {
                Ranges = context.CompletionRanges
            };

            // This is effectively the same as GenerateMemberPresentation, but without the overhead that comes
            // with the flexibility of formatting any time of declared element. We just hard code the format
            var predefinedType = context.PsiModule.GetPredefinedType();
            var parameters     = string.Empty;

            if (eventFunction.Parameters.Length > 0)
            {
                var sb = new StringBuilder();
                for (var i = 0; i < eventFunction.Parameters.Length; i++)
                {
                    if (i > 0)
                    {
                        sb.Append(", ");
                    }

                    var parameter = eventFunction.Parameters[i];
                    var type      = predefinedType.TryGetType(parameter.ClrTypeName, NullableAnnotation.Unknown);
                    var typeName  = type?.GetPresentableName(CSharpLanguage.Instance) ??
                                    parameter.ClrTypeName.ShortName;
                    sb.AppendFormat("{0}{1}{2}", parameter.IsByRef ? "out" : string.Empty,
                                    typeName, parameter.IsArray ? "[]" : string.Empty);
                }
                parameters = sb.ToString();
            }
            var text            = $"{eventFunction.Name}({parameters})";
            var parameterOffset = eventFunction.Name.Length;

            var modifier = showModifier
                ? CSharpDeclaredElementPresenter.Instance.Format(accessRights) + " "
                : string.Empty;

            var psiIconManager = context.BasicContext.LookupItemsOwner.Services.PsiIconManager;

            return(LookupItemFactory.CreateLookupItem(declaredElementInfo)
                   .WithPresentation(item =>
            {
                var displayName = new RichText($"{modifier}{text} {{ ... }}");

                // GenerateMemberPresentation marks everything as bold, and the parameters + block syntax as not important
                var parameterStartOffset = modifier.Length + parameterOffset;
                LookupUtil.MarkAsNotImportant(displayName,
                                              TextRange.FromLength(parameterStartOffset, displayName.Length - parameterStartOffset));
                LookupUtil.AddEmphasize(displayName, new TextRange(modifier.Length, displayName.Length));

                var image = psiIconManager.GetImage(methodDeclaration.DeclaredElement,
                                                    methodDeclaration.DeclaredElement.PresentationLanguage, true);
                var marker = item.Info.Ranges.CreateVisualReplaceRangeMarker();
                return new SimplePresentation(displayName, image, marker);
            })
                   .WithBehavior(_ => new UnityEventFunctionBehavior(myShellLocks, declaredElementInfo, eventFunction, accessRights))
                   .WithMatcher(_ =>
                                new ShiftedDeclaredElementMatcher(eventFunction.Name, modifier.Length, declaredElementInfo,
                                                                  context.BasicContext.IdentifierMatchingStyle)));
        }