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); } }
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); }
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); } }
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); }
public IRearrangeable CreateElement(ISolution solution, ITextControl textControl) { foreach (IRuleDeclaration ruleDeclaration in TextControlToPsi.GetElements <IRuleDeclaration>(solution, textControl)) { return(new RearrangeableRuleDeclaration(ruleDeclaration)); } return(null); }
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); }
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); }
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); } }
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); }
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); }