Reputation: 5063
One of the things that I find hard to keep consistent is the use of int
vs Int32
and bool
vs Boolean
etcetera.
I find it simpler to identify all types by their case and color syntax highlighting...
List<int>
vs
List<Int32>
The latter is cleaner and upholds consistency. A lot of code is littered with both and I'm looking for a refactoring tool to change them all.
Are there any tools that allow me to change all C# built-in types to their .NET Framework types?
Upvotes: 1
Views: 321
Reputation: 5063
I eventually wrote a macro to do this
Option Strict Off
Option Explicit Off
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics
Public Module ReplaceCSharpBuiltInTypesWithTheirFrameworkTypes
Sub ReplaceCSharpBuiltInTypesWithTheirFrameworkTypes()
Dim dictionary As New Collections.Generic.Dictionary(Of String, String)
dictionary.Add("bool", "Boolean")
dictionary.Add("byte", "Byte")
dictionary.Add("sbyte", "SByte")
dictionary.Add("char", "Char")
dictionary.Add("decimal", "Decimal")
dictionary.Add("double", "Double")
dictionary.Add("float", "Single")
dictionary.Add("int", "Int32")
dictionary.Add("uint", "UInt32")
dictionary.Add("long", "Int64")
dictionary.Add("ulong", "UInt64")
dictionary.Add("object", "Object")
dictionary.Add("short", "Int16")
dictionary.Add("ushort", "UInt16")
dictionary.Add("string", "String")
For Each key In dictionary.Keys
DTE.Find.FindWhat = key
DTE.Find.ReplaceWith = dictionary(key)
DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
DTE.Find.MatchCase = True
DTE.Find.MatchWholeWord = True
DTE.Find.MatchInHiddenText = False
DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
DTE.Find.Execute()
Next
End Sub
End Module
Upvotes: 0
Reputation: 64098
Using the Roslyn CTP, the following appears to work in practice:
static SyntaxTree UpdatePredefinedTypes(this SyntaxTree tree)
{
PredefinedTypeSyntax node;
var root = tree.Root;
while (null != (node = root.DescendentNodes()
.OfType<PredefinedTypeSyntax>()
.FirstOrDefault(
syn => redefineMap.ContainsKey(syn.PlainName))))
{
var ident = Syntax.IdentifierName(redefineMap[node.PlainName]);
root = root.ReplaceNode<SyntaxNode, SyntaxNode>(
node,
ident.WithLeadingTrivia(node.GetLeadingTrivia())
.WithTrailingTrivia(node.GetTrailingTrivia()));
}
return SyntaxTree.Create(
tree.FileName,
(CompilationUnitSyntax)root,
tree.Options);
}
When using a proper redefineMap
(e.g. {"int","Int32"}
, {"double","Double"}
) the following program was converted successfully:
using System;
namespace HelloWorld {
class Program {
static void Main(string[] args) {
int x = Int32.Parse("11");
double y = x;
Console.WriteLine("Hello, World! {0}", y);
}
}
}
Output:
using System;
namespace HelloWorld {
class Program {
static void Main(String[] args) {
Int32 x = Int32.Parse("11");
Double y = x;
Console.WriteLine("Hello, World! {0}", y);
}
}
}
When compiling:
var mscorlib = new AssemblyFileReference(
typeof(object).Assembly.Location);
var newTree = UpdatePredefinedTypes(tree);
var compilation = Compilation.Create("HelloWorld")
.AddReferences(mscorlib)
.AddSyntaxTrees(new[] { newTree });
var results = compilation.Emit(File.Create("helloworld.exe"));
Console.WriteLine("Success: {0}", results.Success);
foreach (var message in results.Diagnostics)
{
Console.WriteLine("{0}", message);
}
// C:\tmp\cs>roslyn-test.exe
// Success: True
//
// C:\tmp\cs>dir /b *.exe
// roslyn-test.exe
// helloworld.exe
//
// C:\tmp\cs>helloworld.exe
// Hello, World! 11
//
You can even utilize the Workspace
features to update an entire solution:
var workspace = Workspace.LoadSolution(info.FullName);
var solution = workspace.CurrentSolution;
foreach (var project in solution.Projects
.Where(prj => prj.LanguageServices.Language == "C#"))
{
foreach (var doc in project.Documents
.Where(d => d.SourceCodeKind == SourceCodeKind.Regular
&& d.LanguageServices.Language == "C#"))
{
var tree = SyntaxTree.ParseCompilationUnit(
doc.GetText(),
doc.DisplayName);
var newTree = UpdatePredefinedTypes(tree);
solution = solution.UpdateDocument(doc.Id, newTree.Text);
}
}
workspace.ApplyChanges(workspace.CurrentSolution, solution);
// when running this in VS on itself it correctly updates the project!
Upvotes: 2
Reputation: 38427
If you look at StyleCop, rule SA1121 actually enforces the opposite of what you want (asks you to change Int32
to int
). It's fairly trivial to decompile that rule and create your own StyleCop rule to enforce the opposite.
This isn't automatic, but after you do your initial conversion, you can incorporate it into your builds and then flag any new uses as errors.
Upvotes: 4
Reputation: 112537
I do not know any tools except the search and replace function of VS.
I usually use the c# alias for type declarations and the .NET type when I call static members
int i = Int32.Parse(s);
It is just a personal preference.
Upvotes: 1