Getting selected members and their type

Hi,

I'm writing a small plugin on top of r# 2005 and got stuck with following: I
need to get selected class metadata but I don't know how. By selected I mean
class selected in active code window.

Following the samples and debugger i managed to have reference of
ITypeElement of selected class. Nice. I know class name, namespace and
assembly. Latter is true if element.Module.Name is actually assembly name.

Now I need information on class fields and properties, more specifically
their name and type (string telling me "System.String" would be enough). I
was trying to go with ITypeMember[] members = element.GetMembers() but I
managed to get only member name and if it's a field or property
(implementing IFieldDeclaration, IPropertyDeclaration). How would I get type
name if member is field or propery?





6 comments
Comment actions Permalink

On Tue, 24 Oct 2006 13:37:51 +0200, Urmo <urmo@reverse-skrowdnim.ee> wrote:

Following the samples and debugger i managed to have reference of
ITypeElement of selected class. Nice. I know class name, namespace and
assembly. Latter is true if element.Module.Name is actually assembly
name.


how did you do this? could you paste some sample code pls?

0
Comment actions Permalink

Stefan Kraus wrote:

On Tue, 24 Oct 2006 13:37:51 +0200, Urmo <urmo@reverse-skrowdnim.ee> wrote:

>> Following the samples and debugger i managed to have reference of
>> ITypeElement of selected class. Nice. I know class name, namespace and
>> assembly. Latter is true if element.Module.Name is actually assembly
>> name.


how did you do this? could you paste some sample code pls?


At the moment I am doing something like that in actionhandler Execute:

ITextControl currentControl =
context.GetData(DataConstants.TEXT_CONTROL) as ITextControl;
if (currentControl == null) return;

ISolution solution = context.GetData(DataConstants.SOLUTION) as ISolution;
if (solution == null) return;

IDeclaredElement documentElement =
TextControlToPsi.GetContainingTypeOrTypeMember(solution, currentControl);
if (documentElement == null) return;

ITypeElement typeElement;

if (documentElement is ITypeElement)
typeElement = documentElement as ITypeElement;
else
typeElement = documentElement.GetContainingType();

There is also a way getting IClass

IDeclaredElement declaration =
context.GetData(DataConstants.TYPE_OR_TYPE_MEMBER) as IDeclaredElement;

IClass currentClass = (IClass)((declaration != null &&
declaration.GetContainingType() != null) ?
declaration.GetContainingType() : declaration);

With IClass there is Properties and Fields that also help a bit. I've
dropped the idea to get nice full typename for simple .net types like
int => System.Int32 but i still need to know a little about the type (is
it enumeration, class or struct)

Urmo

0
Comment actions Permalink

Ok, I got it already solved.
PsiManager.GetDeclarationsCache.GetTypeElementByCLRName() was very
helpful method. (element.GetElementType() == DeclaredElementType.ENUM)
enabled me to check if i'm dealing with member type of enumeration.

Next question - how and if I can insert new file to a project?
Especially nice would be to insert it "under" .cs file (like designer.cs
classes).

If anybody is wondering why on earth do I need all this - I'm writing a
plugin that takes active class in IDE and builds most probable
"sceleton" NHibernate mapping file for it, saving me from lot of boring
work :)

Urmo wrote:


With IClass there is Properties and Fields that also help a bit. I've
dropped the idea to get nice full typename for simple .net types like
int => System.Int32 but i still need to know a little about the type (is
it enumeration, class or struct)

Urmo

0
Comment actions Permalink

Hello Urmo,

concering inserting a new file - basically you have two ways for doing this:

1) The simplest one is to use ReSharper API: IProjectFolder.CreateFile will
add the file at the specified path to the project under the folder represented
by 'this' object. ReSharper IProjectFile interface represents a file in a
project,
and you can get the file from anywhere in PSI using IElement.GetContainingFile().ProjectItem
property.
The project items (files and folders) comprise a hierarchy which can be accessed
using IProjectFolder.GetSubItems
and IProjectItem.ParentFolder methods.

This way, however, will not allow you to do the trick the designer does with
putting generated files under
the respective manually edited file.

2) The more complex way: you can leverage Visual Studio API. However, you'll
have to reference EnvDTE, VSIP (Microsoft.VisualStudio.*.Interop) and probably
some other assemblies for that.
Then you can get ReSharper's IProjectFile as before, and obtain the respective
Visual Studio ProjectItem by using
a combination of conversion methods provided by ReSharper and VS. If you
are interested, I'll look into this and provide more info.

Hope this helps.

Regards,
Dmitry Shaporenkov
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"

Ok, I got it already solved.
PsiManager.GetDeclarationsCache.GetTypeElementByCLRName() was very
helpful method. (element.GetElementType() == DeclaredElementType.ENUM)
enabled me to check if i'm dealing with member type of enumeration.

Next question - how and if I can insert new file to a project?
Especially nice would be to insert it "under" .cs file (like
designer.cs classes).

If anybody is wondering why on earth do I need all this - I'm writing
a plugin that takes active class in IDE and builds most probable
"sceleton" NHibernate mapping file for it, saving me from lot of
boring work :)

Urmo wrote:

>> With IClass there is Properties and Fields that also help a bit. I've
>> dropped the idea to get nice full typename for simple .net types like
>> int => System.Int32 but i still need to know a little about the type
>> (is it enumeration, class or struct)
>>
>> Urmo
>>


0
Comment actions Permalink

Thanks, I'll try the first solution.

And another question - is there a way to access
file search + jump functionality with API as it comes with CntrShiftN ?
I.e. if I know a filename (without full path), is there a way to look it up
over entire solution and if found, navigate to it?

Urmo

"Dmitry Shaporenkov (JetBrains)" <dsha@jetbrains.com> wrote in message
news:c8a894d91b71308c8c766c682a785@news.intellij.net...

Hello Urmo,

>

concering inserting a new file - basically you have two ways for doing
this:

>

1) The simplest one is to use ReSharper API: IProjectFolder.CreateFile
will
add the file at the specified path to the project under the folder
represented
by 'this' object. ReSharper IProjectFile interface represents a file in a
project,
and you can get the file from anywhere in PSI using
IElement.GetContainingFile().ProjectItem property.
The project items (files and folders) comprise a hierarchy which can be
accessed using IProjectFolder.GetSubItems
and IProjectItem.ParentFolder methods.

>

This way, however, will not allow you to do the trick the designer does
with putting generated files under the respective manually edited file.

>

2) The more complex way: you can leverage Visual Studio API. However,
you'll have to reference EnvDTE, VSIP (Microsoft.VisualStudio.*.Interop)
and probably some other assemblies for that.
Then you can get ReSharper's IProjectFile as before, and obtain the
respective Visual Studio ProjectItem by using
a combination of conversion methods provided by ReSharper and VS. If you
are interested, I'll look into this and provide more info.

>

Hope this helps.

>

Regards,
Dmitry Shaporenkov
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"

>
>> Ok, I got it already solved.
>> PsiManager.GetDeclarationsCache.GetTypeElementByCLRName() was very
>> helpful method. (element.GetElementType() == DeclaredElementType.ENUM)
>> enabled me to check if i'm dealing with member type of enumeration.
>>
>> Next question - how and if I can insert new file to a project?
>> Especially nice would be to insert it "under" .cs file (like
>> designer.cs classes).
>>
>> If anybody is wondering why on earth do I need all this - I'm writing
>> a plugin that takes active class in IDE and builds most probable
>> "sceleton" NHibernate mapping file for it, saving me from lot of
>> boring work :)
>>
>> Urmo wrote:
>>
>>> With IClass there is Properties and Fields that also help a bit. I've
>>> dropped the idea to get nice full typename for simple .net types like
>>> int => System.Int32 but i still need to know a little about the type
>>> (is it enumeration, class or struct)
>>>
>>> Urmo
>>>
>



0
Comment actions Permalink

Hello Urmo,

if I understand your question correctly, you're looking for a way to navigate
to a file given only the short name of the file.
The implementation of CtrlShiftN is not exposed, however, it is not difficult
to write it yourself. Basically, CtrlShiftN
just uses an RecursiveProjectVisitor for collecting file names:

internal class FileNameCollector : RecursiveProjectVisitor
{
private string myFileName;

public FileNameCollection (string fileName) { myFileName = fileName;
}

public override void VisitProjectFile (IProjectFile projectFile)
{
base.VisitProjectFile (projectFile);
string projectFileName = projectFile.Name;
if (myFileName == projectFileName) // or whatever matching you need
{
// do smth with the IProjectFile
}
}
}


You can use this visitor as follows:

///
FileNameCollector collector = new FileNameCollector("foo.cs");
ISolution currentSolution; // you should have it at hand
currentSolution.Accept(collector);
///




Regards,
Dmitry Shaporenkov
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"

Thanks, I'll try the first solution.

And another question - is there a way to access
file search + jump functionality with API as it comes with
CntrShiftN ?
I.e. if I know a filename (without full path), is there a way to look
it up
over entire solution and if found, navigate to it?
Urmo

"Dmitry Shaporenkov (JetBrains)" <dsha@jetbrains.com> wrote in message
news:c8a894d91b71308c8c766c682a785@news.intellij.net...

>> Hello Urmo,
>>
>> concering inserting a new file - basically you have two ways for
>> doing this:
>>
>> 1) The simplest one is to use ReSharper API:
>> IProjectFolder.CreateFile
>> will
>> add the file at the specified path to the project under the folder
>> represented
>> by 'this' object. ReSharper IProjectFile interface represents a file
>> in a
>> project,
>> and you can get the file from anywhere in PSI using
>> IElement.GetContainingFile().ProjectItem property.
>> The project items (files and folders) comprise a hierarchy which can
>> be
>> accessed using IProjectFolder.GetSubItems
>> and IProjectItem.ParentFolder methods.
>> This way, however, will not allow you to do the trick the designer
>> does with putting generated files under the respective manually
>> edited file.
>>
>> 2) The more complex way: you can leverage Visual Studio API. However,
>> you'll have to reference EnvDTE, VSIP
>> (Microsoft.VisualStudio.*.Interop)
>> and probably some other assemblies for that.
>> Then you can get ReSharper's IProjectFile as before, and obtain the
>> respective Visual Studio ProjectItem by using
>> a combination of conversion methods provided by ReSharper and VS. If
>> you
>> are interested, I'll look into this and provide more info.
>> Hope this helps.
>>
>> Regards,
>> Dmitry Shaporenkov
>> JetBrains, Inc
>> http://www.jetbrains.com
>> "Develop with pleasure!"
>>> Ok, I got it already solved.
>>> PsiManager.GetDeclarationsCache.GetTypeElementByCLRName() was very
>>> helpful method. (element.GetElementType() ==
>>> DeclaredElementType.ENUM) enabled me to check if i'm dealing with
>>> member type of enumeration.
>>>
>>> Next question - how and if I can insert new file to a project?
>>> Especially nice would be to insert it "under" .cs file (like
>>> designer.cs classes).
>>>
>>> If anybody is wondering why on earth do I need all this - I'm
>>> writing a plugin that takes active class in IDE and builds most
>>> probable "sceleton" NHibernate mapping file for it, saving me from
>>> lot of boring work :)
>>>
>>> Urmo wrote:
>>>
>>>> With IClass there is Properties and Fields that also help a bit.
>>>> I've dropped the idea to get nice full typename for simple .net
>>>> types like int => System.Int32 but i still need to know a little
>>>> about the type (is it enumeration, class or struct)
>>>>
>>>> Urmo
>>>>


0

Please sign in to leave a comment.