private static ITreeNode GetCaptureHighlightingRange(
            [NotNull] ITreeNode topDeclaration, [CanBeNull] IFunction thisElement,
            [NotNull] IDeclaredElement capture, out DocumentRange range)
        {
            var declarations = capture.GetDeclarations();

            if (declarations.Count == 0) // accessors 'value' parameter
            {
                var accessor = thisElement as IAccessor;
                if (accessor != null && Equals(accessor.ValueVariable, capture))
                {
                    var identifier = ((IAccessorDeclaration)topDeclaration).NameIdentifier;
                    range = identifier.GetDocumentRange();
                    return(identifier);
                }

                range = DocumentRange.InvalidRange;
                return(null);
            }

            var declaration = declarations[0];

            range = declaration.GetNameDocumentRange();
            var nameEndOffset = range.EndOffsetRange().TextRange.EndOffset;

            var variable = declaration as ILocalVariableDeclaration;

            if (variable != null)
            {
                var multiple = MultipleLocalVariableDeclarationNavigator.GetByDeclarator(variable);
                if (multiple != null && multiple.Declarators[0] == variable)
                {
                    var documentRange = multiple.GetTypeRange();
                    range = documentRange.SetEndTo(nameEndOffset);
                    return(variable);
                }

                return(null);
            }

            var parameter = declaration as IRegularParameterDeclaration;

            if (parameter != null)
            {
                if (range.TextRange.Length < 3)
                {
                    range = parameter.TypeUsage.GetDocumentRange().SetEndTo(nameEndOffset);
                }

                return(parameter);
            }

            var anonymousParameter = declaration as IAnonymousMethodParameterDeclaration;

            if (anonymousParameter != null)
            {
                range = anonymousParameter.TypeUsage.GetDocumentRange().SetEndTo(nameEndOffset);
                return(anonymousParameter);
            }

            return(declaration);
        }
Example #2
0
        private static AfterCompletionHandler BakeAfterComplete([NotNull] ILookupItem lookupItem, [NotNull] ISolution solution, int argumentsCount)
        {
            // sorry, ugly as f**k :(
            return((ITextControl textControl, ref TextRange range, ref TextRange decoration,
                    TailType tailType, ref Suffix suffix, ref IRangeMarker caretMarker) =>
            {
                var psiServices = solution.GetPsiServices();
                psiServices.CommitAllDocuments();

                var allMethods = GetAllTargetMethods(lookupItem);
                if (allMethods.Count == 0)
                {
                    return;
                }

                var reference = TextControlToPsi.GetElement <IReferenceExpression>(solution, textControl.Document, range.StartOffset);
                if (reference == null)
                {
                    return;
                }

                var decorationText = textControl.Document.GetText(decoration);
                var decorationRange = new DocumentRange(textControl.Document, decoration);

                var hasMoreParameters = HasMoreParameters(allMethods, argumentsCount);
                if (!hasMoreParameters) // put caret 'foo(arg){here};'
                {
                    caretMarker = decorationRange.EndOffsetRange().CreateRangeMarker();
                }
                else if (argumentsCount > 0)
                {
                    var parenthesisCloseIndex = decorationText.LastIndexOf(')');
                    if (parenthesisCloseIndex >= 0)
                    {
                        var delta = decoration.Length - parenthesisCloseIndex;
                        caretMarker = decorationRange.EndOffsetRange().Shift(-delta).CreateRangeMarker();
                    }
                }

                var qualifierExpression = reference.QualifierExpression.NotNull("qualifierExpression != null");
                var referencePointer = reference.CreateTreeElementPointer();

                var qualifierText = InsertQualifierAsArgument(
                    qualifierExpression, allMethods, argumentsCount, textControl, decoration, decorationText);

                // TODO: mmm?
                if (!hasMoreParameters && !decorationText.EndsWith(")", StringComparison.Ordinal))
                {
                    caretMarker = caretMarker.DocumentRange.Shift(+qualifierText.Length).CreateRangeMarker();
                }

                // replace qualifier with type (predefined/user type)
                var ownerType = allMethods[0].GetContainingType().NotNull("ownerType != null");
                FixQualifierExpression(textControl, qualifierExpression, ownerType);

                psiServices.CommitAllDocuments();

                var newReference = referencePointer.GetTreeNode();
                if (newReference != null)
                {
                    var keyword = CSharpTypeFactory.GetTypeKeyword(ownerType.GetClrName());
                    if (keyword == null) // bind user type
                    {
                        var newQualifier = (IReferenceExpression)newReference.QualifierExpression;
                        if (newQualifier != null)
                        {
                            var elementInstance = lookupItem.GetDeclaredElement().NotNull("elementInstance != null");
                            newQualifier.Reference.BindTo(ownerType, elementInstance.Substitution);
                        }

                        range = newReference.NameIdentifier.GetDocumentRange().TextRange;
                        decoration = TextRange.InvalidRange;
                    }

                    // show parameter info when needed
                    if (hasMoreParameters)
                    {
                        var factory = solution.GetComponent <LookupItemsOwnerFactory>();
                        var lookupItemsOwner = factory.CreateLookupItemsOwner(textControl);

                        LookupUtil.ShowParameterInfo(solution, textControl, lookupItemsOwner);
                    }
                }

                TipsManager.Instance.FeatureIsUsed(
                    "Plugin.ControlFlow.PostfixTemplates.<static>", textControl.Document, solution);
            });
        }