How can I determine the Type of the object used to generate a completion list?

SyntaxEditor for WPF Forum

Posted 5 years ago by Chris Shaw
Version: 14.2.0610
Avatar

In a C# code editor, I want to restrict the choices that a user will see in the Intelliprompt for certain classes.

For instance, given a class called 'Entity', I only want to display four basic properties in the completion list -- no members inherited from base classes, and no other members defined in the class itself.

As far as I can determine, neither the ICompletionSession nor the Context member of the session have the information that I need -- what Type is being used to generate the list of Completion Items?  If I know that, I can filter the Items in the OnSessionOpening() method of the CompletionProvider, but all I can find is TargetExpression.Value, which gives me the name of the object being targeted, not its Type.

Am I missing something simple (probably...)?

Comments (4)

Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Chris,

Unfortunately the target object type isn't passed along.  The resolver just returns child results based on the resolved result of the context's target expression.

If the target expression is filled in, in OnSessionOpening() you could possibly loop through the results and look at each completion item's Tag property.  If that is an object of type ITypeMemberDefinition, you can see the DeclaringType there and know if the member comes from an Entity class.


Actipro Software Support

Posted 5 years ago by Chris Shaw
Avatar

I thought about trying that, but inheritance makes it difficult (wouldn't ToString() show 'object' as its DeclaringType, for instance -- even if the Target object was 'Entity'?).  Also, the SE has to have done that already, and I was hoping to avoid doing it again...

It also seems like I could use the EditorBrowsable Attribute (at least, some posters to the forum have mentioned that), but I'd need to override *every* member in the heirarchy, just to add the attribute.

Is there any Attribute or Interface strategy that you would suggest to get the kind of 'white-list' effect I'm looking for?  I essentially want to tell the SE that for class 'foo', *only* suggest members of my 'white-list' as possible completions.

Thanks,

--Chris

Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Chris,

The completion can show in two general scenarios.  One is if the user hits Ctrl+Space but there is no "dot" before the caret location.  In that case the completion shows all namespaces, types, members, variables, etc. that are accessible from the context location.  In this scenario, the target expresssion of the context will be null.

In the second scenario, the target expression will be filled in, meaning we are finding the members of something.  The resolution of that "something" does happen internally, and resolver results are returned.  But those resolver results are basically just the members and don't always reference the resolved type, as you saw where members like ToString() come from Object and not Entity.

While you can use EditorBrowsableAttribute to exclude members from ever showing in the completion list, that will affect any types that have those members.  It won't work for a single specific class like you are trying to do.

The only thing I can suggest for your scenario is to possibly first check that there is a target expression.  If there is, scan all the completion items.  If you see any in there that are for members whose DeclaringType is Entity, then you know the entire completion list is for an object of type Entity or an inherited class of it.  Then you can take action to trim down the list as you need.


Actipro Software Support

Answer - Posted 5 years ago by Chris Shaw
Avatar

...and it worked!

I define a property on my target class, and search for it in the completion list items.  The following code gets the type:


private static Type GetTargetType(ICompletionItem item)
{
    var typeDef = (ITypeDefinition)((ITypeMemberResolverResult)item.Tag).Member.DeclaringType;
    var typeName = Assembly.CreateQualifiedName(typeDef.AssemblyName.FullName, typeDef.FullName);
    return Type.GetType(typeName);
}

 

Thanks,

--Chris

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.