QuickFix Create hotspot with type selection

24 views
Skip to first unread message

Pascal Empl

unread,
Jul 9, 2016, 1:04:06 PM7/9/16
to resharper-plugins
I have a quickfix that creates a PropertyDeclaration and i want to that the user can change the type and name of the property in the same way as the "prop" template.

How can i manage that?

Matt Ellis

unread,
Jul 14, 2016, 8:38:35 AM7/14/16
to resharper-plugins
Hi Pascal. You can use LiveTemplatesManager.Instance.CreateHotspotSessionAtopExistingText to add a hotspot to a given text control and range. You need to pass in an array of HotspotInfo, which you can create yourself, or take a look at how the "create from usage" actions handle it, by creating an IntentionResult that populates a list of ITemplateFieldHolders, each of which has a GetInfo method that can get the corresponding HotspotInfo. There are a few helper methods to create these ITemplateFieldHolders, such as FieldDeclarationBuilder, or the classes it uses - ReturnTypeBuilder, and TypeUsageBuilder.

Regards
Matt

Pascal Empl

unread,
Jul 14, 2016, 8:44:32 AM7/14/16
to resharper-plugins
Where can i take a look at the "create from usage" actions?

Matthew Ellis

unread,
Jul 14, 2016, 8:48:12 AM7/14/16
to resharpe...@googlegroups.com
Check out CreateFromUsageActionBase2 and derived classes.

--
You received this message because you are subscribed to the Google Groups "resharper-plugins" group.
To unsubscribe from this group and stop receiving emails from it, send an email to resharper-plug...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Pascal Empl

unread,
Jul 14, 2016, 9:31:04 AM7/14/16
to resharper-plugins
I have a highlighting and for this highlighting a quickfix inherited from QuickFixBase.

This is my current code:

protected override Action<ITextControl> ExecutePsiTransaction(ISolution solution, IProgressIndicator progress)
        {
            var memberReference = mHighlighting.ReferenceExpression.GetConditionalMemberReference();
            if (memberReference == null)
                return null;

            var resolve = memberReference.Resolve();
            if (resolve.ResolveErrorType != ResolveErrorType.OK)
                return null;

            if (resolve.DeclaredElement == null)
                return null;

            var declarations = resolve.DeclaredElement.GetDeclarations<IPropertyDeclaration>();
            if (declarations.Count != 1)
                return null;

            var userControl = new PropertyNameWindow();
            var result = userControl.ShowDialog();
            if (!result.HasValue || !result.Value)
                return null;

            var propDeclaration = declarations[0];
            propDeclaration.NavigateToNode(true);

            var t = CSharpTypeFactory.CreateType("GreenGate.Entity.Models.BaseEntity", mHighlighting.ReferenceExpression.GetPsiModule());

            var vFactory = CSharpElementFactory.GetInstance(mHighlighting.ReferenceExpression.GetPsiModule());

            var navigationPropertyDeclaration = vFactory.CreatePropertyDeclaration(t, userControl.PropertyName.Text);
            navigationPropertyDeclaration.SetAccessRights(AccessRights.PUBLIC);
            navigationPropertyDeclaration.SetVirtual(true);

            var getDec = vFactory.CreateAccessorDeclaration(AccessorKind.GETTER, false);
            var setDec = vFactory.CreateAccessorDeclaration(AccessorKind.SETTER, false);

            navigationPropertyDeclaration.AddAccessorDeclarationAfter(setDec, null);
            navigationPropertyDeclaration.AddAccessorDeclarationAfter(getDec, null);
            
            ModificationUtil.AddChildAfter(propDeclaration, navigationPropertyDeclaration);

            var mappingExpression = vFactory.CreateExpression("$0(a => a.$1).WithMany().HasForeignKey(a => a.$2);", mHighlighting.IsOptional ? "HasOptional" : "HasRequired", userControl.PropertyName.Text, mHighlighting.ReferenceExpression.NameIdentifier.Name);

            ModificationUtil.AddChildAfter(mHighlighting.StatementNode, mappingExpression);

            return null;
        }

Example Code that will be analysed:

public class Entity
{
  public int? Id { get; set; }
}

public class Mapping
{
  public Mapping
  {
    Property<Entity>(m => m.Id);
  }
}

The highlighting is shown in class "Mapping" on "Id". My QuickFix creates now a property in class "Entity" and some code in the constructor of class "Mapping". That code needs the name of the property created in class "Entity".

My code works but with a window where you enter a PropertyName and generates the property with a dummy type. In my opinion my code is an example for "You shouldn't do it like this" but i can't get it work on another way.
Reply all
Reply to author
Forward
0 new messages