From 751e6001f917fee4eee09ee1bbc818a4721efee1 Mon Sep 17 00:00:00 2001 From: GrahamTheCoder Date: Sat, 5 May 2018 15:29:01 +0100 Subject: [PATCH] Convert DateAndTime to DateTime Some things like DateString and setting the system time won't work, but we can always add more special cases later --- .../CSharp/CompilationErrorFixer.cs | 12 +++++- .../CSharp/NodesVisitor.cs | 2 +- .../Util/ISymbolExtensions.cs | 39 ++++++++++++++++--- Tests/CSharp/NamespaceLevelTests.cs | 14 +------ 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/ICSharpCode.CodeConverter/CSharp/CompilationErrorFixer.cs b/ICSharpCode.CodeConverter/CSharp/CompilationErrorFixer.cs index ad4d5ee..975a752 100644 --- a/ICSharpCode.CodeConverter/CSharp/CompilationErrorFixer.cs +++ b/ICSharpCode.CodeConverter/CSharp/CompilationErrorFixer.cs @@ -48,8 +48,16 @@ namespace ICSharpCode.CodeConverter.CSharp .Select(d => compilationUnitSyntax.FindNode(d.Location.SourceSpan)) .OfType() .ToList(); - if (diagnostics.All(d => d.Id != UnresolvedTypeOrNamespaceDiagnosticId) && unusedUsings.Any()) { - compilationUnitSyntax = compilationUnitSyntax.RemoveNodes(unusedUsings, SyntaxRemoveOptions.KeepNoTrivia); + + var nodesWithUnresolvedTypes = diagnostics + .Where(d => d.Id == UnresolvedTypeOrNamespaceDiagnosticId && d.Location.IsInSource) + .Select(d => compilationUnitSyntax.FindNode(d.Location.SourceSpan)) + .ToLookup(d => d.GetAncestor()); + unusedUsings = unusedUsings.Except(nodesWithUnresolvedTypes.Select(g => g.Key)).ToList(); + + if (!nodesWithUnresolvedTypes[null].Any() && unusedUsings.Any()) { + compilationUnitSyntax = + compilationUnitSyntax.RemoveNodes(unusedUsings, SyntaxRemoveOptions.KeepNoTrivia); } return compilationUnitSyntax; diff --git a/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs b/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs index fcee58b..06fd7dd 100644 --- a/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs +++ b/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs @@ -1549,7 +1549,7 @@ namespace ICSharpCode.CodeConverter.CSharp // CSharp allows partial qualification within the current type's parent namespace qualifiedName = qualifiedName.Substring(firstMatch.Length); } - else if (!targetSymbolInfo.IsNamespace() && _importedNamespaces.ContainsKey(typeOrNamespace)) + else if (!targetSymbolInfo.IsNamespace() && _importedNamespaces.ContainsKey(typeOrNamespace) && qualifiedName.StartsWith(typeOrNamespace)) { // An import matches the entire namespace, which means it's not a partially qualified thing that would need extra help in CSharp qualifiedName = qualifiedName.Substring(typeOrNamespace.Length + 1); diff --git a/ICSharpCode.CodeConverter/Util/ISymbolExtensions.cs b/ICSharpCode.CodeConverter/Util/ISymbolExtensions.cs index f099692..d4231c9 100644 --- a/ICSharpCode.CodeConverter/Util/ISymbolExtensions.cs +++ b/ICSharpCode.CodeConverter/Util/ISymbolExtensions.cs @@ -11,6 +11,8 @@ namespace ICSharpCode.CodeConverter.Util #endif static class ISymbolExtensions { + private static readonly string[] TypesToConvertToDateTime = new[] {"DateTime", "DateAndTime" }; + /// /// Checks if 'symbol' is accessible from within 'within'. /// @@ -181,16 +183,41 @@ namespace ICSharpCode.CodeConverter.Util public static string ToMinimalCSharpDisplayString(this ISymbol symbol, SemanticModel vbSemanticModel, int position, SymbolDisplayFormat format = null) { - var output = symbol.ToMinimalDisplayString(vbSemanticModel, position, format); - if (symbol is ITypeSymbol && output == "Date") return "DateTime"; - return output; + if (TryGetSpecialVBTypeConversion(symbol, out var cSharpDisplayString)) return cSharpDisplayString; + return symbol.ToMinimalDisplayString(vbSemanticModel, position, format); } public static string ToCSharpDisplayString(this ISymbol symbol, SymbolDisplayFormat format = null) { - var output = symbol.ToDisplayString(format); - if (symbol is ITypeSymbol && output == "Date") return "DateTime"; - return output; + if (TryGetSpecialVBTypeConversion(symbol, out var cSharpDisplayString)) return cSharpDisplayString; + + return symbol.ToDisplayString(format); + } + + private static bool TryGetSpecialVBTypeConversion(ISymbol symbol, out string cSharpDisplayString) + { + var containingNamespace = symbol?.ContainingNamespace?.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat); + if (containingNamespace == "Microsoft.VisualBasic" || containingNamespace == "System") { + if (symbol is ITypeSymbol && TypesToConvertToDateTime.Contains(symbol.Name)) { + { + cSharpDisplayString = "DateTime"; + return true; + } + } else if (TypesToConvertToDateTime.Contains(symbol.ContainingType?.Name)) { + { + cSharpDisplayString = "DateTime" + "." + symbol.Name; + return true; + } + } + } + + cSharpDisplayString = null; + return false; + } + + private static bool ShouldConvertToDateTime(ITypeSymbol symbol, string fullName) + { + return TypesToConvertToDateTime.Contains(symbol.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat)); } public static bool IsPartialImplementation(this ISymbol declaredSymbol) diff --git a/Tests/CSharp/NamespaceLevelTests.cs b/Tests/CSharp/NamespaceLevelTests.cs index f96fd9c..39818a1 100644 --- a/Tests/CSharp/NamespaceLevelTests.cs +++ b/Tests/CSharp/NamespaceLevelTests.cs @@ -54,19 +54,7 @@ public class Test { TestConversionVisualBasicToCSharp( @"Imports UnrecognizedNamespace", - @"using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Security; -using System.Text; -using System.Threading.Tasks; -using Microsoft.VisualBasic; -using UnrecognizedNamespace;"); + @"using UnrecognizedNamespace;"); } [Fact]