CodeFormatModule to change types from inbuild alias types

I am writing a ICodeCleanupModule as suggested by Ilya on this feature request but am hitting some issues. The code I have is something like this:

CLRTypeName typeName = new CLRTypeName("System.String");
DeclaredTypeFromCLRName newType = new DeclaredTypeFromCLRName(typeName, variable.Module);

localVariableDeclaration.SetType(newType);

If this code is used against a ILocalVariableDeclarationNode instance that is defined as string, the type will not get updated as System.String or String. The type defined against ILocalVariableDeclarationNode for the string declaration is actually System.String under the covers anyway. It looks like ReSharper is using the defined CLR types internally, but always formats code to use the alias types in C#. This means that my formatting plugin will never be able to convert from alias types back to their full CLR type definition.

Any thoughts or pointers?

3 comments
Comment actions Permalink

Yes, you are right.
ReSharper internally handles built-in types and always use keywords.

To overcome this issue, you have to use lower-level API (since tis change
(System.String->string) is handled by high-level API).

For example, high level API - is to set variable type to given IType (as you
do)
Low-level API - to construct ITypeUsageNode as you wish and replace it in
AST (abstract syntax tree).

So use the following:

// create AST fragment for type usage
var typeUsageNode =
CSharpElementFactory.GetInstance(project).CreateTypeUsageNode("String");

// say ReSharper that this type usage points to System.String, so ReSharper
core can insert using directives, or somethig else
((IUserTypeUsageNode)typeUsageNode).ScalarTypeName.Reference.BindTo(new
PredefinedType(project).String.getTypeElement());

// replace AST fragment in actual file
localVariableDeclaration.ToTreeNode().SetTypeUsageNode(typeUsageNode);


--
Eugene Pasynkov
Developer
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"
"Rory Primrose" <no_reply@jetbrains.com> wrote in message
news:31310826.10771213672963963.JavaMail.jive@app4.labs.intellij.net...
>I am writing a ICodeCleanupModule as suggested by Ilya on [this feature
>request|http://www.jetbrains.net/jira/browse/RSRP-60756] but am hitting
>some issues. The code I have is something like this:
>

CLRTypeName typeName = new CLRTypeName("System.String");
DeclaredTypeFromCLRName newType = new DeclaredTypeFromCLRName(typeName,
variable.Module);

>

localVariableDeclaration.SetType(newType);

>

If this code is used against a ILocalVariableDeclarationNode instance that
is defined as string, the type will not get updated as System.String
or String. The type defined against ILocalVariableDeclarationNode for
the string declaration is actually System.String under the covers
anyway. It looks like ReSharper is using the defined CLR types internally,
but always formats code to use the alias types in C#. This means that my
formatting plugin will never be able to convert from alias types back to
their full CLR type definition.

>

Any thoughts or pointers?



0
Comment actions Permalink

Hi Eugene,

Thanks for the quick response. I have tried to add your code, but found that ILocalVariableDeclarationNode doesn't have a SetTypeUsageNode method. It has a TypeUsageNode property, but it is readonly. Any ideas?

I also found another potential issue with writing a format module which I have outlined here.

Cheers

0
Comment actions Permalink

I had a look through Reflector at the SetVar() method which gave me a solution to update the ITypeUsageNode.

// create AST fragment for type usage
IProject project = localVariableDeclaration.GetProject();
ITypeUsageNode typeUsageNode = CSharpElementFactory.GetInstance(project).CreateTypeUsageNode("String");

// say ReSharper that this type usage points to System.String, so ReSharper core can insert using directives, or somethig else
((IUserTypeUsageNode)typeUsageNode).ScalarTypeName.Reference.BindTo(new PredefinedType(project).String.GetTypeElement());

// replace AST fragment in actual file
// localVariableDeclaration.ToTreeNode().SetTypeUsageNode(typeUsageNode);
using (WriteLockCookie.Create(localVariableDeclaration.IsPhysical()))
{
ModificationUtil.ReplaceChild(localVariableDeclaration.TypeUsage, typeUsageNode);
}

0

Please sign in to leave a comment.