private IList <PrefixExpressionContext> FindOriginalContexts([NotNull] PostfixTemplateContext context) { var results = new LocalList <PrefixExpressionContext>(); var images = new List <ExpressionContextImage>(myImages); for (var index = 0; index < images.Count; index++) // order is important { foreach (var expressionContext in context.ExpressionsOrTypes) { if (images[index].MatchesByRangeAndType(expressionContext)) { images[index] = null; results.Add(expressionContext); break; } } } if (results.Count == 0) { var expressions = context.Expressions; foreach (var image in myImages) { if (image != null && image.ContextIndex < expressions.Count) { results.Add(expressions[image.ContextIndex]); } } } return(results.ResultingList()); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { if (context.IsAutoCompletion) { return(null); } var outerExpression = context.OuterExpression; if (outerExpression == null || !outerExpression.CanBeStatement) { return(null); } for (ITreeNode node = outerExpression.Expression;;) { var assignmentExpression = node.GetContainingNode <IAssignmentExpression>(); if (assignmentExpression == null) { break; } // disable 'here.to = "abc";' if (assignmentExpression.Dest.Contains(node)) { return(null); } node = assignmentExpression; } return(new AssignmentItem(outerExpression)); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { if (context.IsAutoCompletion) { foreach (var expressionContext in context.Expressions) { var castExpression = CastExpressionNavigator.GetByOp(expressionContext.Expression); if (castExpression == null) { continue; // available in auto over cast expressions } var expression = ParenthesizedExpressionNavigator.GetByExpression(castExpression); if (expression != null) { continue; // not already parenthesized } return(new ParenthesesItem(expressionContext)); } return(null); } var contexts = CommonUtils.FindExpressionWithValuesContexts(context); if (contexts.Length == 0) { return(null); } return(new ParenthesesItem(contexts)); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var expressionContext = context.Expressions.LastOrDefault(); if (expressionContext == null) { return(null); } if (context.IsAutoCompletion) { if (!expressionContext.CanBeStatement) { return(null); } if (!IsEnumerable(expressionContext)) { return(null); } } if (expressionContext.CanBeStatement) { return(new ForEachStatementItem(expressionContext)); } return(new ForEachExpressionItem(expressionContext)); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var outerExpression = context.OuterExpression; if (outerExpression != null && outerExpression.CanBeStatement) { if (IsNullable(outerExpression)) { if (context.IsAutoCompletion && !MakeSenseToCheckInAuto(outerExpression)) { return(null); // reduce noise } return(new CheckForNullStatementItem("notNull", outerExpression, "if($0!=null)")); } } else if (!context.IsAutoCompletion) { var nullableExpressions = new List <PrefixExpressionContext>(); foreach (var expressionContext in context.Expressions) { if (IsNullable(expressionContext)) { nullableExpressions.Add(expressionContext); } } if (nullableExpressions.Count > 0) { nullableExpressions.Reverse(); return(new CheckForNullExpressionItem("notNull", nullableExpressions.ToArray(), "$0!=null")); } } return(null); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var expressionContext = context.OuterExpression; if (expressionContext == null || !expressionContext.CanBeStatement) { return(null); } var expressionType = expressionContext.Type; if (context.IsAutoCompletion) { if (expressionType.IsUnknown) { return(null); } if (!expressionType.IsObject()) { return(null); } } else { if (expressionType.Classify == TypeClassification.VALUE_TYPE) { return(null); } } return(new LockItem(expressionContext)); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var typeExpression = context.TypeExpression; if (typeExpression == null) { return(CreateExpressionItem(context)); } var typeElement = typeExpression.ReferencedElement as ITypeElement; if (typeElement == null) { return(null); } if (context.IsAutoCompletion) { if (!TypeUtils.IsUsefulToCreateWithNew(typeElement)) { return(null); } } var canInstantiate = TypeUtils.CanInstantiateType(typeElement, typeExpression.Expression); if (canInstantiate != CanInstantiate.No) { var hasParameters = (canInstantiate & CanInstantiate.ConstructorWithParameters) != 0; return(new NewTypeItem(typeExpression, hasParameters)); } return(null); }
public ArgumentItem([NotNull] PrefixExpressionContext[] contexts, [NotNull] PostfixTemplateContext postfixContext) : base("arg", contexts) { var executionContext = postfixContext.ExecutionContext; myLookupItemsOwner = executionContext.LookupItemsOwner; myTemplatesManager = executionContext.LiveTemplatesManager; }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var typeExpression = context.TypeExpression; if (typeExpression != null && typeExpression.ReferencedElement is ITypeElement) { return(new TypeOfItem(typeExpression)); } return(null); }
private static IPostfixLookupItem CreateExpressionItem([NotNull] PostfixTemplateContext context) { var expressionContext = context.InnerExpression; if (expressionContext == null) { return(null); } var invocationExpression = expressionContext.Expression as IInvocationExpression; if (invocationExpression != null) // StringBuilder().new { var reference = invocationExpression.InvokedExpression as IReferenceExpression; if (reference != null) { var declaredElement = reference.Reference.Resolve().DeclaredElement; if (context.IsAutoCompletion) { var typeElement = declaredElement as ITypeElement; if (typeElement != null && TypeUtils.IsUsefulToCreateWithNew(typeElement)) { var canInstantiate = TypeUtils.CanInstantiateType(typeElement, reference); if (canInstantiate != CanInstantiate.No) { return(new NewExpressionItem(expressionContext)); } } } else if (declaredElement == null || declaredElement is ITypeElement) { if (CommonUtils.IsReferenceExpressionsChain(reference)) { return(new NewExpressionItem(expressionContext)); } } } } else if (!context.IsAutoCompletion) // UnresolvedType.new { var reference = expressionContext.Expression as IReferenceExpression; if (reference != null && CommonUtils.IsReferenceExpressionsChain(reference)) { var declaredElement = reference.Reference.Resolve().DeclaredElement; if (declaredElement == null || declaredElement is ITypeElement) { return(new NewTypeItem(expressionContext, hasRequiredArguments: true)); } } } return(null); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var functionDeclaration = context.ContainingFunction; if (functionDeclaration == null) { return(null); } var classLikeDeclaration = functionDeclaration.GetContainingNode <IClassLikeDeclaration>(); if (classLikeDeclaration == null || classLikeDeclaration is IInterfaceDeclaration) { return(null); } if (!context.IsAutoCompletion || functionDeclaration.DeclaredElement is IConstructor) { foreach (var expression in context.Expressions) { if (expression.Type.IsUnknown) { continue; } if (!expression.CanBeStatement) { continue; } // disable over assignments if (expression.Expression is IAssignmentExpression) { return(null); } var reference = expression.Expression as IReferenceExpression; if (reference != null && reference.QualifierExpression == null) { // filter out other fields and properties var target = expression.ReferencedElement; if (target == null || target is IField || target is IProperty) { continue; } } return(CreateItem(expression, expression.Type, functionDeclaration.IsStatic)); } } return(null); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { foreach (var expressionContext in context.Expressions) { var expressionType = expressionContext.Type; if (expressionType.IsResolved && expressionType.IsString()) { return(new ParseItem("tryParse", expressionContext, isTryParse: true)); } } return(null); }
public ILookupItem CreateItem(PostfixTemplateContext context) { foreach (var expressionContext in context.Expressions) { var expressionType = expressionContext.Type; if (expressionType.IsResolved && expressionType.IsString()) { return new ParseItem("parse", expressionContext, isTryParse: false); } } return null; }
public ILookupItem CreateItem(PostfixTemplateContext context) { string lengthName; if (CreateForItem(context, out lengthName)) { var expressionContext = context.InnerExpression; if (expressionContext != null) { return new ReverseForLookupItem(expressionContext, lengthName); } } return null; }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { string lengthName; if (CreateForItem(context, out lengthName)) { var expressionContext = context.InnerExpression; if (expressionContext != null) { return(new ForLookupItem(expressionContext, lengthName)); } } return(null); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { if (context.IsAutoCompletion) { return(null); } var expressions = CommonUtils.FindExpressionWithValuesContexts(context); if (expressions.Length == 0) { return(null); } return(new CastItem(expressions, context)); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { if (context.IsAutoCompletion) { return(null); } var expressions = context.Expressions.Reverse().ToArray(); if (expressions.Length == 0) { return(null); } return(new SelectItem(expressions)); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var expressionContext = context.OuterExpression; if (expressionContext == null || !expressionContext.CanBeStatement) { return(null); } if (context.IsAutoCompletion) { var declaration = context.ContainingFunction; if (declaration == null) { return(null); } var function = declaration.DeclaredElement; if (function == null) { return(null); } var returnType = function.ReturnType; if (returnType.IsVoid()) { return(null); } if (!IsOrCanBecameIterator(declaration, returnType)) { return(null); } var elementType = GetIteratorElementType(returnType, declaration); var conversionRule = expressionContext.Expression.GetTypeConversionRule(); if (!expressionContext.ExpressionType.IsImplicitlyConvertibleTo(elementType, conversionRule)) { return(null); } } return(new YieldItem(expressionContext)); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var booleanExpressions = new LocalList <PrefixExpressionContext>(); var booleanType = context.Reference.GetPredefinedType().Bool; if (booleanType.IsResolved) { var conversionRule = context.Reference.GetTypeConversionRule(); foreach (var expressionContext in context.Expressions) { var expressionType = expressionContext.ExpressionType; if (expressionType.IsResolved) { if (!expressionType.IsImplicitlyConvertibleTo(booleanType, conversionRule) && !IsBooleanExpressionEx(expressionContext.Expression)) { continue; } } else { if (!IsBooleanExpressionEx(expressionContext.Expression)) { continue; } } booleanExpressions.Add(expressionContext); } } if (!context.IsAutoCompletion && booleanExpressions.Count == 0) { booleanExpressions.AddRange(context.Expressions); } if (booleanExpressions.Count > 0) { return(CreateBooleanItem(booleanExpressions.ToArray())); } return(null); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var isAutoCompletion = context.ExecutionContext.IsAutoCompletion; foreach (var expressionContext in context.Expressions) { if (!expressionContext.CanBeStatement) { continue; } if (isAutoCompletion) { // disable for constant expressions if (!expressionContext.Expression.ConstantValue.IsBadValue()) { continue; } var expressionType = expressionContext.Type; if (!expressionType.IsResolved) { continue; } if (expressionType.IsNullable()) { expressionType = expressionType.GetNullableUnderlyingType(); if (expressionType == null || !expressionType.IsResolved) { continue; } } if (!expressionType.IsPredefinedIntegral() && !expressionType.IsEnumType()) { continue; } } return(new SwitchItem(expressionContext)); } return(null); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var expressionContext = context.TypeExpression ?? context.OuterExpression; if (expressionContext == null || !expressionContext.CanBeStatement) { return(null); } var expression = expressionContext.Expression; var referencedType = expressionContext.ReferencedType; if (referencedType != null) // 'Exception.throw' case { if (context.IsAutoCompletion && !IsInstantiableExceptionType(referencedType, expression)) { return(null); } var canInstantiate = TypeUtils.CanInstantiateType(referencedType, expression); var hasParameters = (canInstantiate & CanInstantiate.ConstructorWithParameters) != 0; return(new ThrowByTypeItem(expressionContext, hasParameters)); } bool needFixWithNew; if (CheckExpressionType(expressionContext, out needFixWithNew) || !context.IsAutoCompletion) { var reference = expressionContext.Expression as IReferenceExpression; if (reference != null && CommonUtils.IsReferenceExpressionsChain(reference)) { return(new ThrowByTypeItem(expressionContext, hasRequiredArguments: true)); } return(new ThrowExpressionItem(expressionContext, needFixWithNew)); } return(null); }
public ILookupItem CreateItem(PostfixTemplateContext context) { var booleanExpressions = new LocalList<PrefixExpressionContext>(); var booleanType = context.Reference.GetPredefinedType().Bool; if (booleanType.IsResolved) { var conversionRule = context.Reference.GetTypeConversionRule(); foreach (var expressionContext in context.Expressions) { var expressionType = expressionContext.ExpressionType; if (expressionType.IsResolved) { if (!expressionType.IsImplicitlyConvertibleTo(booleanType, conversionRule) && !IsBooleanExpressionEx(expressionContext.Expression)) continue; } else { if (!IsBooleanExpressionEx(expressionContext.Expression)) continue; } booleanExpressions.Add(expressionContext); } } if (!context.IsAutoCompletion && booleanExpressions.Count == 0) { booleanExpressions.AddRange(context.Expressions); } if (booleanExpressions.Count > 0) { return CreateBooleanItem(booleanExpressions.ToArray()); } return null; }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var expressionContext = context.OuterExpression; if (expressionContext == null || !expressionContext.CanBeStatement) { return(null); } if (context.IsAutoCompletion) { var declaration = context.ContainingFunction; if (declaration == null) { return(null); } var function = declaration.DeclaredElement; if (function == null) { return(null); } var returnType = GetMethodReturnValueType(function, declaration); if (returnType == null) { return(null); } var conversionRule = expressionContext.Expression.GetTypeConversionRule(); if (!expressionContext.ExpressionType.IsImplicitlyConvertibleTo(returnType, conversionRule)) { return(null); } } return(new ReturnLookupItem(expressionContext)); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var expressionContext = context.InnerExpression; if (expressionContext == null) { return(null); } var containingFunction = context.ContainingFunction; if (containingFunction == null) { return(null); } if (context.IsAutoCompletion) { if (!containingFunction.IsAsync) { return(null); } var type = expressionContext.Type; if (!type.IsUnknown && !IsAwaitableType(type)) { return(null); } } if (IsAlreadyAwaited(expressionContext)) { return(null); } return(new AwaitItem(expressionContext)); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { if (context.IsAutoCompletion) { return(null); } // disable .arg template if .arg hotspot is enabled now var textControl = context.ExecutionContext.TextControl; if (textControl.GetData(PostfixArgTemplateExpansion) != null) { return(null); } var expressions = CommonUtils.FindExpressionWithValuesContexts(context, IsNiceArgument); if (expressions.Length == 0) { return(null); } return(new ArgumentItem(expressions, context)); }
public ILookupItem CreateItem(PostfixTemplateContext context) { var outerExpression = context.OuterExpression; if (outerExpression != null && outerExpression.CanBeStatement) { if (IsNullable(outerExpression)) { if (context.IsAutoCompletion && outerExpression.Expression is IAsExpression) return null; return new CheckForNullStatementItem("null", outerExpression, "if($0==null)"); } } else if (!context.IsAutoCompletion) { var innerExpression = context.InnerExpression; if (IsNullable(innerExpression)) { return new CheckForNullExpressionItem("null", innerExpression, "$0==null"); } } return null; }
public CastItem([NotNull] PrefixExpressionContext[] contexts, [NotNull] PostfixTemplateContext postfixContext) : base("cast", contexts) { myTemplatesManager = postfixContext.ExecutionContext.LiveTemplatesManager; }
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); }
protected bool CreateForItem([NotNull] PostfixTemplateContext context, [CanBeNull] out string lengthName) { lengthName = null; var expressionContext = context.InnerExpression; if (expressionContext == null || !expressionContext.CanBeStatement) { return(false); } var expression = expressionContext.Expression; if (context.IsAutoCompletion && !expression.IsPure()) { return(false); } if (expressionContext.Type is IArrayType) { lengthName = "Length"; } else { if (!expressionContext.Type.IsResolved) { return(false); // even in force mode } var psiModule = expressionContext.PostfixContext.PsiModule; var symbolTable = expressionContext.Type.GetSymbolTable(psiModule); var publicProperties = symbolTable.Filter( myPropertyFilter, OverriddenFilter.INSTANCE, new AccessRightsFilter(new ElementAccessContext(expression))); const string countPropertyName = "Count"; var result = publicProperties.GetResolveResult(countPropertyName); var resolveResult = result.DeclaredElement as IProperty; if (resolveResult != null) { if (resolveResult.IsStatic) { return(false); } if (!resolveResult.Type.IsInt()) { return(false); } lengthName = countPropertyName; } else { if (!expressionContext.Type.IsPredefinedIntegralNumeric()) { return(false); } } } return(true); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var contexts = new List <PrefixExpressionContext>(); foreach (var expressionContext in context.ExpressionsOrTypes) { var expression = expressionContext.Expression; if (expression is IReferenceExpression) { // filter out 'too simple' local variable expressions var target = expressionContext.ReferencedElement; if (target is IParameter || target is ILocalVariable) { if (context.IsAutoCompletion) { continue; } } } else if (expression is IAssignmentExpression) { if (context.IsAutoCompletion) { continue; } } if (expressionContext.Type.IsVoid()) { continue; } var referencedType = expressionContext.ReferencedType; if (referencedType != null) { if (context.IsAutoCompletion) { if (TypeUtils.CanInstantiateType(referencedType, expression) == 0) { break; } if (!TypeUtils.IsUsefulToCreateWithNew(referencedType.GetTypeElement())) { break; } } contexts.Add(expressionContext); break; // prevent from 'expr == T.var' => 'var t = expr == T;' } contexts.Add(expressionContext); } var bestContext = contexts.FirstOrDefault(MattersToShowVar) ?? contexts.LastOrDefault(); if (bestContext == null) { return(null); } if (MattersToShowVar(bestContext) || !context.IsAutoCompletion) { var referencedType = bestContext.ReferencedType; if (referencedType != null) { return(new VarByTypeItem(bestContext, referencedType)); } var isConstructorCall = IsConstructorInvocation(bestContext.Expression); if (bestContext.CanBeStatement) { return(new VarStatementItem(bestContext, isConstructorCall)); } return(new VarExpressionItem(bestContext, isConstructorCall)); } return(null); }
public IPostfixLookupItem CreateItem(PostfixTemplateContext context) { var expressionContext = context.OuterExpression; if (expressionContext == null || !expressionContext.CanBeStatement) { return(null); } var expression = expressionContext.Expression; var shouldCreateVariable = true; var disposableType = expression.GetPredefinedType().IDisposable; if (!disposableType.IsResolved) { return(null); } var conversionRule = expression.GetTypeConversionRule(); var expressionType = expressionContext.ExpressionType; if (context.IsAutoCompletion) { if (!expressionType.IsResolved) { return(null); } if (!expressionType.IsImplicitlyConvertibleTo(disposableType, conversionRule)) { return(null); } } if (expressionType.IsResolved && disposableType.Equals(expressionType.ToIType())) { shouldCreateVariable = false; } // check expression is local variable reference var resourceVariable = expressionContext.ReferencedElement as ITypeOwner; if (resourceVariable is ILocalVariable || resourceVariable is IParameter) { shouldCreateVariable = false; } for (ITreeNode node = expression; context.IsAutoCompletion;) { // inspect containing using statements var usingStatement = node.GetContainingNode <IUsingStatement>(); if (usingStatement == null) { break; } // check if expressions is variable declared with using statement var declaration = usingStatement.Declaration; if (resourceVariable is ILocalVariable && declaration != null) { foreach (var member in declaration.DeclaratorsEnumerable) { if (Equals(member.DeclaredElement, resourceVariable)) { return(null); } } } // check expression is already in using statement expression if (declaration == null) { foreach (var expr in usingStatement.ExpressionsEnumerable) { if (MiscUtil.AreExpressionsEquivalent(expr, expression)) { return(null); } } } node = usingStatement; } return(new UsingItem(expressionContext, shouldCreateVariable)); }
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); }