Skip to content

Commit ba17216

Browse files
Merge pull request #732 from Yozer/fix-names
VB -> C#: Converter takes the property name from interface instead of the concrete class.
2 parents 67da715 + 1ff025d commit ba17216

File tree

26 files changed

+171
-42
lines changed

26 files changed

+171
-42
lines changed

CodeConverter/CSharp/CommonConversions.cs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4-
using System.Reflection;
54
using System.Runtime.CompilerServices;
65
using System.Runtime.InteropServices;
76
using System.Threading.Tasks;
87
using ICSharpCode.CodeConverter.Shared;
98
using ICSharpCode.CodeConverter.Util;
10-
using ICSharpCode.CodeConverter.Util.FromRoslyn;
119
using Microsoft.CodeAnalysis;
1210
using Microsoft.CodeAnalysis.CSharp;
1311
using Microsoft.CodeAnalysis.Editing;
@@ -273,7 +271,7 @@ public SyntaxToken ConvertIdentifier(SyntaxToken id, bool isAttribute = false, S
273271
if (id.SyntaxTree == _semanticModel.SyntaxTree) {
274272
var idSymbol = _semanticModel.GetSymbolInfo(id.Parent).Symbol ?? _semanticModel.GetDeclaredSymbol(id.Parent);
275273
if (idSymbol != null && !String.IsNullOrWhiteSpace(idSymbol.Name)) {
276-
text = WithDeclarationName(id, idSymbol, text);
274+
text = WithDeclarationName(id, idSymbol, text, _typeContext.AssembliesBeingConverted);
277275
var normalizedText = text.WithHalfWidthLatinCharacters();
278276
if (idSymbol.IsConstructor() && isAttribute) {
279277
text = idSymbol.ContainingType.Name;
@@ -306,10 +304,32 @@ public SyntaxToken ConvertIdentifier(SyntaxToken id, bool isAttribute = false, S
306304
/// <seealso cref="DeclarationNodeVisitor.WithDeclarationNameCasingAsync(VBSyntax.NamespaceBlockSyntax, ISymbol)"/>
307305
/// <seealso cref="CommonConversions.WithDeclarationNameCasing(TypeSyntax, ITypeSymbol)"/>
308306
/// </summary>
309-
private static string WithDeclarationName(SyntaxToken id, ISymbol idSymbol, string text)
307+
private static string WithDeclarationName(SyntaxToken id, ISymbol idSymbol, string text, IEnumerable<IAssemblySymbol> assembliesBeingConverted)
310308
{
311309
//This also covers the case when the name is different (in VB you can have method X implements IFoo.Y), but doesn't resolve any resulting name clashes
312-
var baseSymbol = idSymbol.IsKind(SymbolKind.Method) || idSymbol.IsKind(SymbolKind.Property) ? idSymbol.FollowProperty(s => s.BaseMember()).Last() : idSymbol;
310+
var assemblyIdentities = assembliesBeingConverted.Select(t => t.Identity);
311+
ISymbol baseSymbol = default;
312+
var containingType = idSymbol.ContainingType;
313+
314+
if (idSymbol.IsKind(SymbolKind.Method) || idSymbol.IsKind(SymbolKind.Property))
315+
{
316+
var possibleSymbols = idSymbol.FollowProperty(s => s.BaseMember());
317+
foreach (var possibleSymbol in possibleSymbols)
318+
{
319+
if (!assemblyIdentities.Contains(possibleSymbol.ContainingAssembly.Identity) && possibleSymbol.ContainingType.Equals(containingType))
320+
{
321+
baseSymbol = possibleSymbol;
322+
break;
323+
}
324+
325+
baseSymbol = possibleSymbol;
326+
}
327+
}
328+
else
329+
{
330+
baseSymbol = idSymbol;
331+
}
332+
313333
bool isDeclaration = baseSymbol.Locations.Any(l => l.SourceSpan == id.Span);
314334
bool isPartial = baseSymbol.IsPartialClassDefinition() || baseSymbol.IsPartialMethodDefinition() ||
315335
baseSymbol.IsPartialMethodImplementation();

CodeConverter/CSharp/DeclarationNodeVisitor.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,11 @@ internal class DeclarationNodeVisitor : VBasic.VisualBasicSyntaxVisitor<Task<CSh
3131
private static readonly Type DllImportType = typeof(DllImportAttribute);
3232
private static readonly Type CharSetType = typeof(CharSet);
3333
private static readonly SyntaxToken SemicolonToken = SyntaxFactory.Token(Microsoft.CodeAnalysis.CSharp.SyntaxKind.SemicolonToken);
34-
private readonly CSharpCompilation _csCompilation;
3534
private readonly SyntaxGenerator _csSyntaxGenerator;
3635
private readonly Compilation _vbCompilation;
3736
private readonly SemanticModel _semanticModel;
3837
private readonly Dictionary<VBSyntax.StatementSyntax, MemberDeclarationSyntax[]> _additionalDeclarations = new Dictionary<VBSyntax.StatementSyntax, MemberDeclarationSyntax[]>();
39-
private readonly TypeContext _typeContext = new TypeContext();
38+
private readonly TypeContext _typeContext;
4039
private uint _failedMemberConversionMarkerCount;
4140
private readonly HashSet<string> _extraUsingDirectives = new HashSet<string>();
4241
private readonly VisualBasicEqualityComparison _visualBasicEqualityComparison;
@@ -51,12 +50,13 @@ internal class DeclarationNodeVisitor : VBasic.VisualBasicSyntaxVisitor<Task<CSh
5150
internal HoistedNodeState AdditionalLocals => _typeContext.HoistedState;
5251

5352
public DeclarationNodeVisitor(Document document, Compilation compilation, SemanticModel semanticModel,
54-
CSharpCompilation csCompilation, SyntaxGenerator csSyntaxGenerator)
53+
CSharpCompilation csCompilation, SyntaxGenerator csSyntaxGenerator,
54+
IEnumerable<IAssemblySymbol> assembliesBeingConverted)
5555
{
5656
_vbCompilation = compilation;
5757
_semanticModel = semanticModel;
58-
_csCompilation = csCompilation;
5958
_csSyntaxGenerator = csSyntaxGenerator;
59+
_typeContext = new TypeContext {AssembliesBeingConverted = assembliesBeingConverted};
6060
_visualBasicEqualityComparison = new VisualBasicEqualityComparison(_semanticModel, _extraUsingDirectives);
6161
TriviaConvertingDeclarationVisitor = new CommentConvertingVisitorWrapper(this, _semanticModel.SyntaxTree);
6262
var expressionEvaluator = new ExpressionEvaluator(semanticModel, _visualBasicEqualityComparison);
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
namespace ICSharpCode.CodeConverter.CSharp
1+
using System.Collections.Generic;
2+
using Microsoft.CodeAnalysis;
3+
4+
namespace ICSharpCode.CodeConverter.CSharp
25
{
36
internal interface ITypeContext
47
{
58
AdditionalInitializers Initializers { get; }
69
MethodsWithHandles MethodsWithHandles { get; }
710
HoistedNodeState HoistedState { get; }
11+
IEnumerable<IAssemblySymbol> AssembliesBeingConverted { get; }
812
bool Any();
913
}
1014
}

CodeConverter/CSharp/TypeContext.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using Microsoft.CodeAnalysis;
23

34
namespace ICSharpCode.CodeConverter.CSharp
45
{
@@ -10,6 +11,7 @@ internal class TypeContext : ITypeContext
1011
public MethodsWithHandles MethodsWithHandles => _contextStack.Peek().Methods;
1112

1213
public HoistedNodeState HoistedState { get; internal set; } = new HoistedNodeState();
14+
public IEnumerable<IAssemblySymbol> AssembliesBeingConverted { get; internal set; }
1315

1416
public void Push(MethodsWithHandles methodWithHandles, AdditionalInitializers additionalInitializers)
1517
{

CodeConverter/CSharp/VBToCSConversion.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ public class VBToCSConversion : ILanguageConversion
2525
private const string UnresolvedNamespaceDiagnosticId = "CS0246";
2626
private const string FabricatedAssemblyName = ISymbolExtensions.ForcePartialTypesAssemblyName;
2727
private VBToCSProjectContentsConverter _vbToCsProjectContentsConverter;
28-
private IProgress<ConversionProgress> _progress;
2928
private CancellationToken _cancellationToken;
3029

3130
public ConversionOptions ConversionOptions { get; set; }
3231

33-
public async Task<IProjectContentsConverter> CreateProjectContentsConverterAsync(Project project, IProgress<ConversionProgress> progress, CancellationToken cancellationToken)
32+
public async Task<IProjectContentsConverter> CreateProjectContentsConverterAsync(Project project,
33+
IEnumerable<IAssemblySymbol> assembliesBeingConverted, IProgress<ConversionProgress> progress,
34+
CancellationToken cancellationToken)
3435
{
35-
_progress = progress;
3636
_cancellationToken = cancellationToken;
3737
bool useProjectLevelWinformsAdjustments = project.AssemblyName != FabricatedAssemblyName;
38-
_vbToCsProjectContentsConverter = new VBToCSProjectContentsConverter(ConversionOptions, useProjectLevelWinformsAdjustments, progress, cancellationToken);
38+
_vbToCsProjectContentsConverter = new VBToCSProjectContentsConverter(ConversionOptions, useProjectLevelWinformsAdjustments, assembliesBeingConverted, progress, cancellationToken);
3939
await _vbToCsProjectContentsConverter.InitializeSourceAsync(project);
4040
return _vbToCsProjectContentsConverter;
4141
}

CodeConverter/CSharp/VBToCSProjectContentsConverter.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ internal class VBToCSProjectContentsConverter : IProjectContentsConverter
2222
{
2323
private readonly ConversionOptions _conversionOptions;
2424
private readonly bool _useProjectLevelWinformsAdjustments;
25+
private readonly IEnumerable<IAssemblySymbol> _assembliesBeingConverted;
2526
private CSharpCompilation _csharpViewOfVbSymbols;
2627
private Dictionary<string, string> _designerToResxRelativePath;
2728
private Project _convertedCsProject;
@@ -30,10 +31,13 @@ internal class VBToCSProjectContentsConverter : IProjectContentsConverter
3031
private readonly IProgress<ConversionProgress> _progress;
3132
private readonly CancellationToken _cancellationToken;
3233

33-
public VBToCSProjectContentsConverter(ConversionOptions conversionOptions, bool useProjectLevelWinformsAdjustments, IProgress<ConversionProgress> progress, CancellationToken cancellationToken)
34+
public VBToCSProjectContentsConverter(ConversionOptions conversionOptions,
35+
bool useProjectLevelWinformsAdjustments, IEnumerable<IAssemblySymbol> assembliesBeingConverted,
36+
IProgress<ConversionProgress> progress, CancellationToken cancellationToken)
3437
{
3538
_conversionOptions = conversionOptions;
36-
this._useProjectLevelWinformsAdjustments = useProjectLevelWinformsAdjustments;
39+
_useProjectLevelWinformsAdjustments = useProjectLevelWinformsAdjustments;
40+
_assembliesBeingConverted = assembliesBeingConverted;
3741
_progress = progress;
3842
_cancellationToken = cancellationToken;
3943
OptionalOperations = new OptionalOperations(conversionOptions.AbandonOptionalTasksAfter, progress, cancellationToken);
@@ -68,7 +72,7 @@ private async Task<Project> WithProjectLevelWinformsAdjustmentsAsync(Project pro
6872

6973
public async Task<SyntaxNode> SingleFirstPassAsync(Document document)
7074
{
71-
return await VisualBasicConverter.ConvertCompilationTreeAsync(document, _csharpViewOfVbSymbols, _csharpReferenceProject, OptionalOperations, _cancellationToken);
75+
return await VisualBasicConverter.ConvertCompilationTreeAsync(document, _csharpViewOfVbSymbols, _csharpReferenceProject, _assembliesBeingConverted, OptionalOperations, _cancellationToken);
7276
}
7377

7478
public async Task<(Project project, List<WipFileConversion<DocumentId>> firstPassDocIds)> GetConvertedProjectAsync(WipFileConversion<SyntaxNode>[] firstPassResults)

CodeConverter/CSharp/VisualBasicConverter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Threading.Tasks;
34
using ICSharpCode.CodeConverter.Shared;
45
using Microsoft.CodeAnalysis;
56
using Microsoft.CodeAnalysis.CSharp;
67
using Microsoft.CodeAnalysis.Editing;
7-
using Microsoft.CodeAnalysis.Formatting;
88
using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax;
99
using CSS = Microsoft.CodeAnalysis.CSharp.Syntax;
1010
using System.Threading;
11-
using ICSharpCode.CodeConverter.VB;
1211

1312
namespace ICSharpCode.CodeConverter.CSharp
1413
{
1514
internal static class VisualBasicConverter
1615
{
1716
public static async Task<SyntaxNode> ConvertCompilationTreeAsync(Document document,
1817
CSharpCompilation csharpViewOfVbSymbols, Project csharpReferenceProject,
18+
IEnumerable<IAssemblySymbol> assembliesBeingConverted,
1919
OptionalOperations optionalOperations, CancellationToken cancellationToken)
2020
{
2121
document = await document.WithExpandedRootAsync(cancellationToken);
@@ -29,7 +29,7 @@ public static async Task<SyntaxNode> ConvertCompilationTreeAsync(Document docume
2929
var csSyntaxGenerator = SyntaxGenerator.GetGenerator(csharpReferenceProject);
3030
var semanticModel = compilation.GetSemanticModel(tree, true);
3131
var visualBasicSyntaxVisitor = new
32-
DeclarationNodeVisitor(document, compilation, semanticModel, csharpViewOfVbSymbols, csSyntaxGenerator);
32+
DeclarationNodeVisitor(document, compilation, semanticModel, csharpViewOfVbSymbols, csSyntaxGenerator, assembliesBeingConverted);
3333
var converted = await root.AcceptAsync<CSS.CompilationUnitSyntax>(visualBasicSyntaxVisitor.TriviaConvertingDeclarationVisitor);
3434

3535
return optionalOperations.MapSourceTriviaToTargetHandled(root, converted, document);

CodeConverter/ILanguageConversion.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ SyntaxNode GetSurroundedNode(IEnumerable<SyntaxNode> descendantNodes,
2424
string TargetLanguage { get; }
2525
ConversionOptions ConversionOptions { get; set; }
2626

27-
Task<IProjectContentsConverter> CreateProjectContentsConverterAsync(Project project, IProgress<ConversionProgress> progress, CancellationToken cancellationToken);
27+
Task<IProjectContentsConverter> CreateProjectContentsConverterAsync(Project project,
28+
IEnumerable<IAssemblySymbol> assembliesBeingConverted, IProgress<ConversionProgress> progress,
29+
CancellationToken cancellationToken);
2830
string PostTransformProjectFile(string xml);
2931

3032
Task<Document> CreateProjectDocumentFromTreeAsync(SyntaxTree tree, IEnumerable<MetadataReference> references);

CodeConverter/Shared/ProjectConversion.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ private ProjectConversion(IProjectContentsConverter projectContentsConverter, IE
6262
document = await WithAnnotatedSelectionAsync(document, conversionOptions.SelectedTextSpan);
6363
}
6464

65-
var projectContentsConverter = await languageConversion.CreateProjectContentsConverterAsync(document.Project, progress, cancellationToken);
65+
var assemblyBeingConverted = (await document.Project.GetCompilationAsync(cancellationToken)).Assembly;
66+
var assembliesBeingConverted = new[] {assemblyBeingConverted};
67+
var projectContentsConverter = await languageConversion.CreateProjectContentsConverterAsync(document.Project, assembliesBeingConverted, progress, cancellationToken);
6668

6769
document = projectContentsConverter.SourceProject.GetDocument(document.Id);
6870

@@ -79,15 +81,15 @@ private static ConversionResult GetSingleResultForDocument(ConversionResult[] co
7981
}
8082

8183
public static async IAsyncEnumerable<ConversionResult> ConvertProject(Project project,
82-
ILanguageConversion languageConversion, IProgress<ConversionProgress> progress, [EnumeratorCancellation] CancellationToken cancellationToken,
84+
ILanguageConversion languageConversion, IProgress<ConversionProgress> progress,
85+
IEnumerable<IAssemblySymbol> assembliesBeingConverted,
86+
[EnumeratorCancellation] CancellationToken cancellationToken,
8387
params (string Find, string Replace, bool FirstOnly)[] replacements)
8488
{
8589
progress ??= new Progress<ConversionProgress>();
8690
using var roslynEntryPoint = await RoslynEntryPointAsync(progress);
87-
88-
var projectContentsConverter = await languageConversion.CreateProjectContentsConverterAsync(project, progress, cancellationToken);
91+
var projectContentsConverter = await languageConversion.CreateProjectContentsConverterAsync(project, assembliesBeingConverted, progress, cancellationToken);
8992
var sourceFilePaths = project.Documents.Concat(projectContentsConverter.SourceProject.AdditionalDocuments).Select(d => d.FilePath).ToImmutableHashSet();
90-
project = projectContentsConverter.SourceProject;
9193
var convertProjectContents = ConvertProjectContents(projectContentsConverter, languageConversion, progress, cancellationToken);
9294

9395
var results = WithProjectFile(projectContentsConverter, languageConversion, sourceFilePaths, convertProjectContents, replacements);

CodeConverter/Shared/SolutionConverter.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Linq;
55
using System.Text.RegularExpressions;
66
using System.Threading;
7+
using System.Threading.Tasks;
78
using ICSharpCode.CodeConverter.Util;
89
using Microsoft.CodeAnalysis;
910

@@ -53,24 +54,27 @@ private SolutionConverter(string solutionFilePath,
5354
_cancellationToken = cancellationToken;
5455
}
5556

56-
public IAsyncEnumerable<ConversionResult> Convert()
57+
public async Task<IAsyncEnumerable<ConversionResult>> Convert()
5758
{
5859
var projectsToUpdateReferencesOnly = _projectsToConvert.First().Solution.Projects.Except(_projectsToConvert);
5960
var solutionResult = string.IsNullOrWhiteSpace(_sourceSolutionContents) ? Enumerable.Empty<ConversionResult>() : ConvertSolutionFile().Yield();
60-
return ConvertProjects()
61+
var convertedProjects = await ConvertProjects();
62+
return convertedProjects
6163
.Concat(UpdateProjectReferences(projectsToUpdateReferencesOnly).Concat(solutionResult).ToAsyncEnumerable());
6264
}
6365

64-
private IAsyncEnumerable<ConversionResult> ConvertProjects()
66+
private async Task<IAsyncEnumerable<ConversionResult>> ConvertProjects()
6567
{
66-
return _projectsToConvert.ToAsyncEnumerable().SelectMany(project => ConvertProject(project));
68+
var assemblies = _projectsToConvert.Select(t => t.GetCompilationAsync(_cancellationToken));
69+
var assembliesBeingConverted = (await Task.WhenAll(assemblies)).Select(t => t.Assembly).ToList();
70+
return _projectsToConvert.ToAsyncEnumerable().SelectMany(project => ConvertProject(project, assembliesBeingConverted));
6771
}
6872

69-
private IAsyncEnumerable<ConversionResult> ConvertProject(Project project)
73+
private IAsyncEnumerable<ConversionResult> ConvertProject(Project project, IEnumerable<IAssemblySymbol> assembliesBeingConverted)
7074
{
7175
var replacements = _projectReferenceReplacements.ToArray();
7276
_progress.Report(new ConversionProgress($"Converting {project.Name}..."));
73-
return ProjectConversion.ConvertProject(project, _languageConversion, _progress, _cancellationToken, replacements);
77+
return ProjectConversion.ConvertProject(project, _languageConversion, _progress, assembliesBeingConverted, _cancellationToken, replacements);
7478
}
7579

7680
private IEnumerable<ConversionResult> UpdateProjectReferences(IEnumerable<Project> projectsToUpdateReferencesOnly)

0 commit comments

Comments
 (0)