コード例 #1
0
            private static PostfixTemplateContext TryReparseWith([NotNull] ISolution solution, [NotNull] ITextControl textControl, [NotNull] string reparseString)
            {
                var offset   = textControl.Caret.Offset();
                var document = textControl.Document;

                try
                {
                    document.InsertText(offset, reparseString);

                    solution.GetPsiServices().Files.CommitAllDocuments();

                    foreach (var position in TextControlToPsi.GetElements <ITreeNode>(solution, document, offset))
                    {
                        var templateContextFactory = LanguageManager.Instance.TryGetService <IPostfixTemplateContextFactory>(position.Language);
                        if (templateContextFactory != null)
                        {
                            var executionContext = new PostfixTemplateExecutionContext(
                                solution, textControl, position.GetSettingsStore(), reparseString, false);

                            return(templateContextFactory.TryCreate(position, executionContext));
                        }
                    }

                    return(null);
                }
                finally
                {
                    var reparseRange = TextRange.FromLength(offset, reparseString.Length);
                    document.DeleteText(reparseRange);
                }
            }
コード例 #2
0
        public static ICSharpStatement FixExpressionToStatement(DocumentRange expressionRange, [NotNull] IPsiServices psiServices)
        {
            var solution = psiServices.Solution;
            var offset   = expressionRange.TextRange.StartOffset;
            var document = expressionRange.Document;

            var expressions = TextControlToPsi.GetElements <IRazorImplicitExpression>(solution, document, offset);

            foreach (var razorExpression in expressions)
            {
                var razorRange = razorExpression.GetDocumentRange();

                const string commandName = "Replacing razor expression with statement";
                using (solution.CreateTransactionCookie(
                           DefaultAction.Commit, commandName, NullProgressIndicator.Instance))
                {
                    razorRange.Document.ReplaceText(razorRange.TextRange, "@using(null){}");
                }

                solution.GetPsiServices().Files.CommitAllDocuments();

                var statements = TextControlToPsi.GetElements <IUsingStatement>(solution, document, offset);
                foreach (var razorStatement in statements)
                {
                    return(razorStatement);
                }

                break;
            }

            return(null);
        }
コード例 #3
0
            private IList <IPostfixLookupItem> TryReparseWith([NotNull] ISolution solution, [NotNull] ITextControl textControl,
                                                              [NotNull] string templateName, [NotNull] string reparseString)
            {
                var offset   = textControl.Caret.Offset();
                var document = textControl.Document;

                try
                {
                    document.InsertText(offset, reparseString);
                    solution.GetPsiServices().CommitAllDocuments();

                    var itemsOwner       = myItemsOwnerFactory.CreateLookupItemsOwner(textControl);
                    var executionContext = new PostfixExecutionContext(
                        myLifetime, solution, textControl, itemsOwner, reparseString, false);

                    foreach (var position in TextControlToPsi.GetElements <ITokenNode>(solution, document, offset))
                    {
                        var postfixContext = myTemplatesManager.IsAvailable(position, executionContext);
                        if (postfixContext == null)
                        {
                            continue;
                        }

                        return(myTemplatesManager.CollectItems(postfixContext, templateName: templateName));
                    }

                    return(null);
                }
                finally
                {
                    var reparseRange = TextRange.FromLength(offset, reparseString.Length);
                    document.DeleteText(reparseRange);
                }
            }
コード例 #4
0
            private IReferenceExpression FindReferenceExpression([NotNull] ITextControl textControl, [NotNull] ISolution solution)
            {
                var dotRange = myDotRangeMarker.DocumentRange;

                if (!dotRange.IsValid())
                {
                    return(null);
                }

                var tokenOffset = dotRange.TextRange.StartOffset;

                foreach (var token in TextControlToPsi.GetElements <ITokenNode>(solution, textControl.Document, tokenOffset))
                {
                    if (token.GetTokenType() == CSharpTokenType.DOT)
                    {
                        var expression = token.Parent as IReferenceExpression;
                        if (expression != null)
                        {
                            return(expression);
                        }
                    }
                }

                return(null);
            }
コード例 #5
0
        public IRearrangeable CreateElement(ISolution solution, ITextControl textControl)
        {
            foreach (IRuleDeclaration ruleDeclaration in TextControlToPsi.GetElements <IRuleDeclaration>(solution, textControl))
            {
                return(new RearrangeableRuleDeclaration(ruleDeclaration));
            }

            return(null);
        }
コード例 #6
0
        public static ICSharpTypeDeclaration FindFirstCharpTypeDeclarationInDocument(ISolution solution, IDocument document)
        {
            for (int i = document.DocumentRange.StartOffset; i < document.DocumentRange.EndOffset; i++)
            {
                var declaration = TextControlToPsi.GetElements <ICSharpTypeDeclaration>(solution, new DocumentOffset(document, i)).FirstOrDefault();

                if (declaration != null)
                {
                    return(declaration);
                }
            }
            return(null);
        }
コード例 #7
0
            private static bool TryPlaceCaretSmart([NotNull] ISolution solution, [NotNull] ITextControl textControl,
                                                   [NotNull] PsiLanguageType language, TextRange range)
            {
                foreach (var tokenNode in TextControlToPsi.GetElements <ITokenNode>(solution, textControl.Document, range.EndOffset))
                {
                    if (!tokenNode.Language.IsLanguage(language))
                    {
                        continue;
                    }

                    var tokenType = tokenNode.GetTokenType();
                    if (tokenType == CSharpTokenType.LT)
                    {
                        var typeArguments = tokenNode.Parent as ITypeArgumentList;
                        if (typeArguments == null)
                        {
                            continue;
                        }

                        var endOffset = tokenNode.GetDocumentRange().TextRange.EndOffset;
                        textControl.Caret.MoveTo(endOffset, CaretVisualPlacement.DontScrollIfVisible);
                        return(true);
                    }

                    if (tokenType == CSharpTokenType.LPARENTH)
                    {
                        var invocation = tokenNode.Parent as IInvocationExpression;
                        if (invocation == null || invocation.RPar == null)
                        {
                            continue;
                        }

                        var reference = invocation.InvocationExpressionReference;
                        if (reference.Resolve().ResolveErrorType == ResolveErrorType.OK)
                        {
                            var offset = invocation.RPar.GetDocumentRange().TextRange.EndOffset;
                            textControl.Caret.MoveTo(offset, CaretVisualPlacement.DontScrollIfVisible);
                            return(true);
                        }
                    }
                }

                return(false);
            }
コード例 #8
0
            private static IInvocationExpression FindFakeInvocation([NotNull] ITextControl textControl, [NotNull] ISolution solution, int offset)
            {
                foreach (var invocationExpression in TextControlToPsi.GetElements <IInvocationExpression>(solution, textControl.Document, offset))
                {
                    var referenceExpression = invocationExpression.InvokedExpression as IReferenceExpression;
                    if (referenceExpression == null)
                    {
                        continue;
                    }

                    var nameIdentifier = referenceExpression.NameIdentifier;
                    if (nameIdentifier == null)
                    {
                        continue;
                    }

                    if (nameIdentifier.Name == CASE_COMPLETION_NAME)
                    {
                        return(invocationExpression);
                    }
                }

                return(null);
            }
            public override void Accept(
                ITextControl textControl, TextRange nameRange, LookupItemInsertType lookupItemInsertType,
                Suffix suffix, ISolution solution, bool keepCaretStill)
            {
                base.Accept(textControl, nameRange, lookupItemInsertType, suffix, solution, keepCaretStill);

                var psiServices = solution.GetPsiServices();
                var startOffset = nameRange.StartOffset;
                var suffix1     = suffix;

                psiServices.Files.CommitAllDocuments();

                var hotspotInfo = psiServices.DoTransaction(
                    commandName: typeof(CSharpTypeParameterFromUsageItemProvider).FullName,
                    func: () =>
                {
                    using (WriteLockCookie.Create(true))
                    {
                        var typeParameterName = Info.Text;
                        var referenceName     = TextControlToPsi
                                                .GetElements <IReferenceName>(solution, textControl.Document, startOffset)
                                                .FirstOrDefault(x => x.NameIdentifier != null && x.NameIdentifier.Name == typeParameterName);

                        if (referenceName == null)
                        {
                            return(null);
                        }

                        var methodDeclaration = referenceName.GetContainingNode <IMethodDeclaration>();
                        if (methodDeclaration == null)
                        {
                            return(null);
                        }

                        var factory = CSharpElementFactory.GetInstance(methodDeclaration);

                        var lastTypeParameter = methodDeclaration.TypeParameterDeclarations.LastOrDefault();
                        var newTypeParameter  = methodDeclaration.AddTypeParameterAfter(
                            factory.CreateTypeParameterOfMethodDeclaration(typeParameterName), anchor: lastTypeParameter);

                        return(new HotspotInfo(
                                   templateField: new TemplateField(typeParameterName, initialRange: 0),
                                   documentRanges: new[] { newTypeParameter.GetDocumentRange(), referenceName.GetDocumentRange() }));
                    }
                });

                if (hotspotInfo == null)
                {
                    return;
                }

                // do not provide hotspots when item is completed with spacebar
                if (suffix1.HasPresentation && suffix1.Presentation == ' ')
                {
                    return;
                }

                var endRange = hotspotInfo.Ranges[1].EndOffsetRange().TextRange;

                var session = LiveTemplatesManager.Instance.CreateHotspotSessionAtopExistingText(
                    solution, endRange, textControl, LiveTemplatesManager.EscapeAction.RestoreToOriginalText, hotspotInfo);

                session.Execute();
            }
        protected TStatement PutStatementCaret([NotNull] ITextControl textControl, [NotNull] TStatement statement)
        {
            foreach (var child in statement.Children())
            {
                var returnStatement = UnwrapFromBraces(child) as IReturnStatement;
                if (returnStatement == null)
                {
                    continue;
                }

                var uncheckedExpression = returnStatement.Value as IUncheckedExpression;
                if (uncheckedExpression == null)
                {
                    continue;
                }

                var checkedExpression = uncheckedExpression.Operand as ICheckedExpression;
                if (checkedExpression == null)
                {
                    continue;
                }

                if (checkedExpression.Operand is ILiteralExpression)
                {
                    var pointer     = statement.CreateTreeElementPointer();
                    var rangeMarker = statement.GetDocumentRange().CreateRangeMarker();

                    var psiServices = checkedExpression.GetPsiServices();
                    var caretRange  = returnStatement.GetDocumentRange().TextRange;

                    // drop caret marker expression and commit PSI
                    textControl.Caret.MoveTo(caretRange.StartOffset, CaretVisualPlacement.DontScrollIfVisible);
                    textControl.Document.DeleteText(caretRange);

                    psiServices.Files.CommitAllDocuments();

                    var fixedStatement = pointer.GetTreeNode();
                    if (fixedStatement != null)
                    {
                        return(fixedStatement);
                    }

                    var textRange = rangeMarker.DocumentRange.TextRange;
                    if (textRange.IsValid)
                    {
                        var newStatements = TextControlToPsi.GetElements <TStatement>(psiServices.Solution, textControl.Document, textRange.StartOffset);

                        foreach (var newStatement in newStatements)
                        {
                            var offset = newStatement.GetDocumentStartOffset();
                            if (offset.TextRange.StartOffset == textRange.StartOffset)
                            {
                                return(newStatement);
                            }
                        }
                    }

                    return(null);
                }
            }

            // at the end of the statement otherwise...
            {
                var endOffset = statement.GetDocumentRange().TextRange.EndOffset;
                textControl.Caret.MoveTo(endOffset, CaretVisualPlacement.DontScrollIfVisible);
                return(statement);
            }
        }
コード例 #11
0
        public void Accept(ITextControl textControl, TextRange nameRange, LookupItemInsertType insertType,
                           Suffix suffix, ISolution solution, bool keepCaretStill)
        {
            textControl.Document.InsertText(
                nameRange.EndOffset, myReparseString, TextModificationSide.RightSide);

            solution.GetPsiServices().CommitAllDocuments();

            var itemsOwnerFactory = solution.GetComponent <LookupItemsOwnerFactory>();
            var templatesManager  = solution.GetComponent <PostfixTemplatesManager>();
            var lookupItemsOwner  = itemsOwnerFactory.CreateLookupItemsOwner(textControl);

            PostfixTemplateContext postfixContext = null;
            var identifierOffset = (textControl.Caret.Offset() - myReparseString.Length);

            foreach (var position in TextControlToPsi
                     .GetElements <ITokenNode>(solution, textControl.Document, identifierOffset))
            {
                var executionContext = new PostfixExecutionContext(
                    myLifetime, solution, textControl, lookupItemsOwner, myReparseString, false);

                postfixContext = templatesManager.IsAvailable(position, executionContext);
                if (postfixContext != null)
                {
                    break;
                }
            }

            TipsManager.Instance.FeatureIsUsed(
                "Plugin.ControlFlow.PostfixTemplates." + myShortcut, textControl.Document, solution);

            Assertion.AssertNotNull(postfixContext, "postfixContext != null");

            var expressions = FindOriginalContexts(postfixContext);

            Assertion.Assert(expressions.Count > 0, "expressions.Count > 0");

            if (expressions.Count > 1 && myExpressionIndex == -1)
            {
                // rollback document changes to hide reparse string from user
                var chooser = solution.GetComponent <ExpressionChooser>();

                var postfixRange = GetPostfixRange(textControl, nameRange);
                var postfixText  = textControl.Document.GetText(postfixRange);
                textControl.Document.ReplaceText(postfixRange, string.Empty);

                chooser.Execute(myLifetime, textControl, expressions,
                                postfixText, ExpressionSelectTitle, index =>
                {
                    myExpressionIndex = index;

                    // yep, run accept recursively, now with selected item index
                    var locks = solution.GetComponent <IShellLocks>();
                    const string commandName = "PostfixTemplates.Accept";

                    locks.ReentrancyGuard.ExecuteOrQueue(commandName, () =>
                    {
                        locks.ExecuteWithReadLock(() =>
                        {
                            var processor = solution.GetComponent <ICommandProcessor>();
                            using (processor.UsingCommand(commandName))
                            {
                                var text = postfixText.Substring(0, postfixText.Length - myReparseString.Length);
                                textControl.Document.InsertText( // bring back ".name__"
                                    postfixRange.StartOffset, text, TextModificationSide.RightSide);

                                Accept(textControl, nameRange, insertType, suffix, solution, keepCaretStill);
                            }
                        });
                    });
                });
                return;
            }

            Assertion.Assert(myExpressionIndex >= 0, "myExpressionIndex >= 0");
            Assertion.Assert(myExpressionIndex < expressions.Count, "myExpressionIndex < expressions.Count");

            var expressionContext = expressions[myExpressionIndex];

            TNode newNode;

            using (WriteLockCookie.Create())
            {
                var fixedContext = postfixContext.FixExpression(expressionContext);

                var expression = fixedContext.Expression;
                Assertion.Assert(expression.IsPhysical(), "expression.IsPhysical()");

                newNode = ExpandPostfix(fixedContext);
                Assertion.AssertNotNull(newNode, "newNode != null");
                Assertion.Assert(newNode.IsPhysical(), "newNode.IsPhysical()");
            }

            AfterComplete(textControl, newNode);
        }
コード例 #12
0
        public void Accept(ITextControl textControl, TextRange nameRange, LookupItemInsertType insertType,
                           Suffix suffix, ISolution solution, bool keepCaretStill)
        {
            // todo: carefully review and document all of this :\
            var reparseString = Info.ReparseString;

            // so we inserted '.__' and get '2 + 2.__' just like in code completion reparse
            textControl.Document.InsertText(nameRange.EndOffset, reparseString, TextModificationSide.RightSide);

            solution.GetPsiServices().Files.CommitAllDocuments();

            var executionContext = new PostfixTemplateExecutionContext(
                solution, textControl, Info.ExecutionContext.SettingsStore, Info.ReparseString, Info.ExecutionContext.IsPreciseMode);

            PostfixTemplateContext postfixContext = null;

            foreach (var element in TextControlToPsi.GetElements <ITreeNode>(solution, textControl.Document, nameRange.EndOffset))
            {
                var contextFactory = LanguageManager.Instance.TryGetService <IPostfixTemplateContextFactory>(element.Language);
                if (contextFactory == null)
                {
                    continue;
                }

                postfixContext = contextFactory.TryCreate(element, executionContext);
                if (postfixContext != null)
                {
                    break;
                }
            }

            // todo: [R#] good feature id, looks at source templates 'Accept()'
            TipsManager.Instance.FeatureIsUsed(
                "Plugin.ControlFlow.PostfixTemplates." + Info.Text, textControl.Document, solution);

            Assertion.AssertNotNull(postfixContext, "postfixContext != null");

            var expressions = FindOriginalContexts(postfixContext);

            Assertion.Assert(expressions.Count > 0, "expressions.Count > 0");

            if (expressions.Count > 1 && myExpressionIndex == -1)
            {
                // rollback document changes to hide reparse string from user
                var chooser = solution.GetComponent <ExpressionChooser>();

                var postfixRange = GetPostfixRange(textControl, nameRange);
                var postfixText  = textControl.Document.GetText(postfixRange);
                textControl.Document.ReplaceText(postfixRange, string.Empty);

                chooser.Execute(
                    EternalLifetime.Instance, textControl, expressions, postfixText,
                    ExpressionSelectTitle, continuation: index =>
                {
                    myExpressionIndex = index;

                    // yep, run accept recursively, now with selected item index
                    var locks = solution.GetComponent <IShellLocks>();
                    const string commandName = "PostfixTemplates.Accept";

                    locks.ReentrancyGuard.ExecuteOrQueue(commandName, () =>
                    {
                        locks.ExecuteWithReadLock(() =>
                        {
                            var processor = solution.GetComponent <ICommandProcessor>();
                            using (processor.UsingCommand(commandName))
                            {
                                var text = postfixText.Substring(0, postfixText.Length - reparseString.Length);

                                // todo: don't like it very much, is there a better way to solve this?
                                textControl.Document.InsertText( // bring back ".name__"
                                    postfixRange.StartOffset, text, TextModificationSide.RightSide);

                                // argh!
                                Accept(textControl, nameRange, insertType, suffix, solution, keepCaretStill);
                            }
                        });
                    });
                });

                return;
            }

            Assertion.Assert(myExpressionIndex >= 0, "myExpressionIndex >= 0");
            Assertion.Assert(myExpressionIndex < expressions.Count, "myExpressionIndex < expressions.Count");

            var expressionContext = expressions[myExpressionIndex];

            ITreeNode newNode;

            using (WriteLockCookie.Create())
            {
                var fixedContext = postfixContext.FixExpression(expressionContext);

                var expression = fixedContext.Expression;
                Assertion.Assert(expression.IsPhysical(), "expression.IsPhysical()");

                newNode = ExpandPostfix(fixedContext);
                Assertion.AssertNotNull(newNode, "newNode != null");
                Assertion.Assert(newNode.IsPhysical(), "newNode.IsPhysical()");
            }

            AfterComplete(textControl, newNode);
        }