Skip to content

Commit c9b73c6

Browse files
Merge remote-tracking branch 'origin/master'
# Conflicts: # Tests/CSharp/MultiFileSolutionAndProjectTests.cs
2 parents 0cab9bc + ba17216 commit c9b73c6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+17173
-14299
lines changed

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,6 @@ dotnet_diagnostic.RCS1123.severity = none
149149

150150
# Default severity for analyzer diagnostics with category 'Performance' - turn this up to warn when looking for performance issues
151151
dotnet_analyzer_diagnostic.category-Performance.severity = suggestion
152+
153+
# CC0097: You have missing/unexistent parameters in Xml Docs
154+
dotnet_diagnostic.CC0097.severity = none

.github/workflows/dotnet.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
build:
1111
runs-on: windows-latest
1212
env:
13-
BuildVersion: '8.2.3'
13+
BuildVersion: '8.2.4'
1414
BuildPlatform: Any CPU
1515
BuildTarget: Release
1616
steps:

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,30 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1010

1111
### VB -> C#
1212

13+
* Prevent overrides and overloads appearing on the same property [#681](https://github.com/icsharpcode/CodeConverter/issues/681)
14+
* Convert `Select x = ` into `let x = ` within Linq [#717](https://github.com/icsharpcode/CodeConverter/issues/717)
1315

1416
### C# -> VB
1517

1618

17-
## [8.2.3] - 2021-04-04
19+
## [8.2.4] - 2021-05-04
1820

1921
### Command line
22+
2023
* The --Core-Only flag no longer requires a value [#704](https://github.com/icsharpcode/CodeConverter/issues/704)
2124

2225

2326
### VB -> C#
27+
2428
* Deal with NullReferenceException caused by Nothing literal [#707](https://github.com/icsharpcode/CodeConverter/issues/707)
2529
* Include text of region which can't be converted
2630
* Convert region names
2731
* All handlers from multi-line handles syntax now converted [#701](https://github.com/icsharpcode/CodeConverter/issues/701)
2832
* Implicilty typed inherited events no longer create extra delegates [#700](https://github.com/icsharpcode/CodeConverter/issues/700)
2933
* Keep optional parameters for parameterized properties [#642](https://github.com/icsharpcode/CodeConverter/issues/642)
3034
* Maintain leading whitespace in comments [#711](https://github.com/icsharpcode/CodeConverter/issues/711)
35+
* Avoid XmlException when referencing certain nuget packages [#714](https://github.com/icsharpcode/CodeConverter/issues/714)
36+
* Use explicit type as default for array creation [#713](https://github.com/icsharpcode/CodeConverter/issues/713)
3137

3238
### C# -> VB
3339

CodeConverter/CSharp/BuiltInVisualBasicOperatorSubstitutions.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using System.Linq.Expressions;
1818
using System.Threading.Tasks;
1919
using Microsoft.CodeAnalysis.Operations;
20+
using Microsoft.CodeAnalysis.VisualBasic;
2021

2122
namespace ICSharpCode.CodeConverter.CSharp
2223
{
@@ -92,11 +93,9 @@ private static VBSyntax.ExpressionSyntax ArgComparedToNull(VBSyntax.BinaryExpres
9293
return null;
9394
}
9495

95-
private async Task<ExpressionSyntax> ConvertIsOrIsNotExpressionArgAsync(VBSyntax.ExpressionSyntax binaryExpressionArg)
96-
{
97-
return (ExpressionSyntax) (await ConvertMyGroupCollectionPropertyGetWithUnderlyingFieldAsync(binaryExpressionArg)
98-
?? await binaryExpressionArg.AcceptAsync(_triviaConvertingVisitor));
99-
}
96+
private async Task<ExpressionSyntax> ConvertIsOrIsNotExpressionArgAsync(VBSyntax.ExpressionSyntax binaryExpressionArg) =>
97+
await ConvertMyGroupCollectionPropertyGetWithUnderlyingFieldAsync(binaryExpressionArg)
98+
?? await binaryExpressionArg.AcceptAsync<ExpressionSyntax>(_triviaConvertingVisitor);
10099

101100
private async Task<ExpressionSyntax> ConvertMyGroupCollectionPropertyGetWithUnderlyingFieldAsync(SyntaxNode node)
102101
{
@@ -106,8 +105,8 @@ private async Task<ExpressionSyntax> ConvertMyGroupCollectionPropertyGetWithUnde
106105
return await ConvertMyGroupCollectionPropertyGetWithUnderlyingFieldAsync(co.Operand.Syntax);
107106
case IPropertyReferenceOperation pro when pro.Property.IsMyGroupCollectionProperty():
108107
var associatedField = pro.Property.GetAssociatedField();
109-
var propertyReferenceOperation = ((IPropertyReferenceOperation)pro.Instance);
110-
var qualification = await propertyReferenceOperation.Syntax.AcceptAsync<ExpressionSyntax>(_triviaConvertingVisitor);
108+
var propertyReferenceSyntax = (VisualBasicSyntaxNode)((IPropertyReferenceOperation)pro.Instance).Syntax;
109+
var qualification = await propertyReferenceSyntax.AcceptAsync<ExpressionSyntax>(_triviaConvertingVisitor);
111110
return SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, qualification, SyntaxFactory.IdentifierName(associatedField.Name));
112111
default:
113112
return null;

CodeConverter/CSharp/CommentConvertingVisitorWrapper.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,18 @@ internal class CommentConvertingVisitorWrapper
1818
{
1919
private readonly VBasic.VisualBasicSyntaxVisitor<Task<CS.CSharpSyntaxNode>> _wrappedVisitor;
2020
private readonly SyntaxTree _syntaxTree;
21+
private static readonly CSSyntax.LiteralExpressionSyntax _dummyLiteral = ValidSyntaxFactory.DefaultExpression;
22+
private static readonly CSSyntax.StatementSyntax _dummyStatement = CS.SyntaxFactory.EmptyStatement();
23+
private static readonly CSSyntax.CompilationUnitSyntax _dummyCompilationUnit = CS.SyntaxFactory.CompilationUnit();
2124

2225
public CommentConvertingVisitorWrapper(VisualBasicSyntaxVisitor<Task<CSharpSyntaxNode>> wrappedVisitor, SyntaxTree syntaxTree)
2326
{
2427
_wrappedVisitor = wrappedVisitor;
2528
_syntaxTree = syntaxTree;
2629
}
2730

28-
public async Task<T> AcceptAsync<T>(SyntaxNode vbNode, SourceTriviaMapKind sourceTriviaMap) where T : CS.CSharpSyntaxNode
29-
{
30-
return await ConvertHandledAsync<T>(vbNode, sourceTriviaMap);
31-
}
31+
public async Task<T> AcceptAsync<T>(VisualBasicSyntaxNode vbNode, SourceTriviaMapKind sourceTriviaMap) where T : CS.CSharpSyntaxNode =>
32+
await ConvertHandledAsync<T>(vbNode, sourceTriviaMap);
3233

3334
public async Task<SeparatedSyntaxList<TOut>> AcceptAsync<TIn, TOut>(SeparatedSyntaxList<TIn> vbNodes, SourceTriviaMapKind sourceTriviaMap) where TIn : VBasic.VisualBasicSyntaxNode where TOut : CS.CSharpSyntaxNode
3435
{
@@ -41,7 +42,7 @@ public async Task<SeparatedSyntaxList<TOut>> AcceptAsync<TIn, TOut>(SeparatedSyn
4142
return CS.SyntaxFactory.SeparatedList(convertedNodes, convertedSeparators);
4243
}
4344

44-
private async Task<T> ConvertHandledAsync<T>(SyntaxNode vbNode, SourceTriviaMapKind sourceTriviaMap) where T : CS.CSharpSyntaxNode
45+
private async Task<T> ConvertHandledAsync<T>(VisualBasicSyntaxNode vbNode, SourceTriviaMapKind sourceTriviaMap) where T : CS.CSharpSyntaxNode
4546
{
4647
try {
4748
var converted = (T)await _wrappedVisitor.Visit(vbNode);
@@ -50,9 +51,12 @@ private async Task<T> ConvertHandledAsync<T>(SyntaxNode vbNode, SourceTriviaMapK
5051
: sourceTriviaMap == SourceTriviaMapKind.SubNodesOnly
5152
? converted
5253
: WithSourceMapping(vbNode, converted);
53-
} catch (Exception e) when (typeof(T).IsAssignableFrom(typeof(CSSyntax.EmptyStatementSyntax))) {
54-
var dummyStatement = (T)(object)CS.SyntaxFactory.EmptyStatement();
55-
return dummyStatement.WithCsTrailingErrorComment((VBasic.VisualBasicSyntaxNode)vbNode, e);
54+
} catch (Exception e) when (_dummyLiteral is T dummy) {
55+
return dummy.WithCsTrailingErrorComment(vbNode, e);
56+
} catch (Exception e) when (_dummyStatement is T dummy) {
57+
return dummy.WithCsTrailingErrorComment(vbNode, e);
58+
} catch (Exception e) when (_dummyCompilationUnit is T dummy) {
59+
return dummy.WithCsTrailingErrorComment(vbNode, e);
5660
} catch (Exception e) when (!(e is ExceptionWithNodeInformation)) {
5761
throw e.WithNodeInformation(vbNode);
5862
}

CodeConverter/CSharp/CommonConversions.cs

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
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;
13-
using Microsoft.CodeAnalysis.CSharp.Syntax;
1411
using Microsoft.CodeAnalysis.Editing;
1512
using Microsoft.CodeAnalysis.FindSymbols;
1613
using Microsoft.CodeAnalysis.Operations;
@@ -64,11 +61,11 @@ public CommonConversions(Document document, SemanticModel semanticModel,
6461
WinformsConversions = new WinformsConversions(typeContext);
6562
}
6663

67-
public async Task<(IReadOnlyCollection<(VariableDeclarationSyntax Decl, ITypeSymbol Type)> Variables, IReadOnlyCollection<CSharpSyntaxNode> Methods)> SplitVariableDeclarationsAsync(
64+
public async Task<(IReadOnlyCollection<(CSSyntax.VariableDeclarationSyntax Decl, ITypeSymbol Type)> Variables, IReadOnlyCollection<CSharpSyntaxNode> Methods)> SplitVariableDeclarationsAsync(
6865
VariableDeclaratorSyntax declarator, HashSet<ILocalSymbol> symbolsToSkip = null, bool preferExplicitType = false)
6966
{
7067
var vbInitValue = GetInitializerToConvert(declarator);
71-
var initializerOrMethodDecl = await vbInitValue.AcceptAsync(TriviaConvertingExpressionVisitor);
68+
var initializerOrMethodDecl = await vbInitValue.AcceptAsync<CSharpSyntaxNode>(TriviaConvertingExpressionVisitor);
7269
var vbInitializerTypeInfo = vbInitValue != null ? _semanticModel.GetTypeInfo(vbInitValue) : default(TypeInfo?);
7370
var vbInitializerType = vbInitValue != null ? vbInitializerTypeInfo.Value.Type : default(ITypeSymbol);
7471

@@ -82,7 +79,7 @@ public CommonConversions(Document document, SemanticModel semanticModel,
8279
requireExplicitTypeForAll |= vbInitIsNothingLiteral || isAnonymousFunction;
8380
}
8481

85-
var csVars = new Dictionary<string, (VariableDeclarationSyntax Decl, ITypeSymbol Type)>();
82+
var csVars = new Dictionary<string, (CSSyntax.VariableDeclarationSyntax Decl, ITypeSymbol Type)>();
8683
var csMethods = new List<CSharpSyntaxNode>();
8784

8885
foreach (var name in declarator.Names) {
@@ -124,7 +121,7 @@ public bool ShouldPreferExplicitType(VBSyntax.ExpressionSyntax exp,
124121
return shouldPreferExplicitType;
125122
}
126123

127-
private async Task<EqualsValueClauseSyntax> ConvertEqualsValueClauseSyntaxAsync(
124+
private async Task<CSSyntax.EqualsValueClauseSyntax> ConvertEqualsValueClauseSyntaxAsync(
128125
VariableDeclaratorSyntax vbDeclarator, VBSyntax.ModifiedIdentifierSyntax vbName,
129126
VBSyntax.ExpressionSyntax vbInitValue,
130127
ITypeSymbol declaredSymbolType,
@@ -136,7 +133,7 @@ private async Task<EqualsValueClauseSyntax> ConvertEqualsValueClauseSyntaxAsync(
136133
bool declaredConst = declaredSymbol is IFieldSymbol fieldSymbol && fieldSymbol.IsConst ||
137134
declaredSymbol is ILocalSymbol localSymbol && localSymbol.IsConst;
138135

139-
EqualsValueClauseSyntax equalsValueClauseSyntax;
136+
CSSyntax.EqualsValueClauseSyntax equalsValueClauseSyntax;
140137
if (await GetInitializerFromNameAndTypeAsync(declaredSymbolType, vbName, initializerOrMethodDecl) is ExpressionSyntax
141138
adjustedInitializerExpr)
142139
{
@@ -180,9 +177,9 @@ public static string GetInitialValueFunctionName(VBSyntax.ModifiedIdentifierSynt
180177
return "initial" + vbName.Identifier.ValueText.ToPascalCase();
181178
}
182179

183-
private VariableDeclarationSyntax CreateVariableDeclaration(VariableDeclaratorSyntax vbDeclarator, bool preferExplicitType,
180+
private CSSyntax.VariableDeclarationSyntax CreateVariableDeclaration(VariableDeclaratorSyntax vbDeclarator, bool preferExplicitType,
184181
bool requireExplicitTypeForAll, ITypeSymbol vbInitializerType, ITypeSymbol declaredSymbolType,
185-
EqualsValueClauseSyntax equalsValueClauseSyntax, IMethodSymbol initSymbol, CSSyntax.VariableDeclaratorSyntax v)
182+
CSSyntax.EqualsValueClauseSyntax equalsValueClauseSyntax, IMethodSymbol initSymbol, CSSyntax.VariableDeclaratorSyntax v)
186183
{
187184
var requireExplicitType = requireExplicitTypeForAll ||
188185
vbInitializerType != null && !Equals(declaredSymbolType, vbInitializerType);
@@ -257,7 +254,7 @@ private async Task<CSharpSyntaxNode> GetInitializerFromNameAndTypeAsync(ITypeSym
257254
var arrayTypeSyntax = ((ArrayTypeSyntax)GetTypeSyntax(typeSymbol)).WithRankSpecifiers(rankSpecifiersWithSizes);
258255
if (rankSpecifiersWithSizes.SelectMany(ars => ars.Sizes).Any(e => !e.IsKind(CSSyntaxKind.OmittedArraySizeExpression))) {
259256
initializer = SyntaxFactory.ArrayCreationExpression(arrayTypeSyntax);
260-
} else if (initializer is ImplicitArrayCreationExpressionSyntax iaces && iaces.Initializer != null) {
257+
} else if (initializer is CSSyntax.ImplicitArrayCreationExpressionSyntax iaces && iaces.Initializer != null) {
261258
initializer = SyntaxFactory.ArrayCreationExpression(arrayTypeSyntax, iaces.Initializer);
262259
}
263260
}
@@ -274,7 +271,7 @@ public SyntaxToken ConvertIdentifier(SyntaxToken id, bool isAttribute = false, S
274271
if (id.SyntaxTree == _semanticModel.SyntaxTree) {
275272
var idSymbol = _semanticModel.GetSymbolInfo(id.Parent).Symbol ?? _semanticModel.GetDeclaredSymbol(id.Parent);
276273
if (idSymbol != null && !String.IsNullOrWhiteSpace(idSymbol.Name)) {
277-
text = WithDeclarationName(id, idSymbol, text);
274+
text = WithDeclarationName(id, idSymbol, text, _typeContext.AssembliesBeingConverted);
278275
var normalizedText = text.WithHalfWidthLatinCharacters();
279276
if (idSymbol.IsConstructor() && isAttribute) {
280277
text = idSymbol.ContainingType.Name;
@@ -307,10 +304,32 @@ public SyntaxToken ConvertIdentifier(SyntaxToken id, bool isAttribute = false, S
307304
/// <seealso cref="DeclarationNodeVisitor.WithDeclarationNameCasingAsync(VBSyntax.NamespaceBlockSyntax, ISymbol)"/>
308305
/// <seealso cref="CommonConversions.WithDeclarationNameCasing(TypeSyntax, ITypeSymbol)"/>
309306
/// </summary>
310-
private static string WithDeclarationName(SyntaxToken id, ISymbol idSymbol, string text)
307+
private static string WithDeclarationName(SyntaxToken id, ISymbol idSymbol, string text, IEnumerable<IAssemblySymbol> assembliesBeingConverted)
311308
{
312309
//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
313-
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+
314333
bool isDeclaration = baseSymbol.Locations.Any(l => l.SourceSpan == id.Span);
315334
bool isPartial = baseSymbol.IsPartialClassDefinition() || baseSymbol.IsPartialMethodDefinition() ||
316335
baseSymbol.IsPartialMethodImplementation();
@@ -349,11 +368,13 @@ public SyntaxTokenList ConvertModifiers(SyntaxNode node, IReadOnlyCollection<Syn
349368

350369
private static bool? RequiresNewKeyword(ISymbol declaredSymbol)
351370
{
352-
if (!(declaredSymbol is IMethodSymbol methodSymbol)) return null;
353-
if (declaredSymbol.IsOverride ) return false;
354-
var methodSignature = methodSymbol.GetUnqualifiedMethodSignature(true);
355-
return declaredSymbol.ContainingType.FollowProperty(s => s.BaseType).Skip(1).Any(t => t.GetMembers()
356-
.Any(s => s.Name == declaredSymbol.Name && s is IMethodSymbol m && m.GetUnqualifiedMethodSignature(true) == methodSignature));
371+
if (declaredSymbol.IsOverride) return false;
372+
if (declaredSymbol is IPropertySymbol propertySymbol || declaredSymbol is IMethodSymbol methodSymbol) {
373+
var methodSignature = declaredSymbol.GetUnqualifiedMethodOrPropertySignature(true);
374+
return declaredSymbol.ContainingType.FollowProperty(s => s.BaseType).Skip(1).Any(t => t.GetMembers()
375+
.Any(s => s.Name == declaredSymbol.Name && (s is IPropertySymbol || s is IMethodSymbol) && s.GetUnqualifiedMethodOrPropertySignature(true) == methodSignature));
376+
}
377+
return null;
357378
}
358379

359380
private static bool ContextHasIdenticalDefaults(TokenContext context, TokenContext[] contextsWithIdenticalDefaults, ISymbol declaredSymbol)
@@ -511,10 +532,10 @@ private async Task<ExpressionSyntax> IncreaseArrayUpperBoundExpressionAsync(VBSy
511532
{
512533
// These attributes' semantic effects are expressed differently in CSharp.
513534
return await attributeList.Attributes.Where(a => !IsExtensionAttribute(a) && !IsOutAttribute(a))
514-
.SelectAsync(async a => (CSSyntax.AttributeListSyntax)await a.AcceptAsync(TriviaConvertingExpressionVisitor));
535+
.SelectAsync(async a => await a.AcceptAsync<CSSyntax.AttributeListSyntax>(TriviaConvertingExpressionVisitor));
515536
}
516537

517-
public static AttributeArgumentListSyntax CreateAttributeArgumentList(params AttributeArgumentSyntax[] attributeArgumentSyntaxs)
538+
public static CSSyntax.AttributeArgumentListSyntax CreateAttributeArgumentList(params CSSyntax.AttributeArgumentSyntax[] attributeArgumentSyntaxs)
518539
{
519540
return SyntaxFactory.AttributeArgumentList(SyntaxFactory.SeparatedList(attributeArgumentSyntaxs));
520541
}
@@ -524,7 +545,7 @@ public static CSSyntax.LocalDeclarationStatementSyntax CreateLocalVariableDeclar
524545
return SyntaxFactory.LocalDeclarationStatement(CreateVariableDeclarationAndAssignment(variableName, initValue));
525546
}
526547

527-
public static VariableDeclarationSyntax CreateVariableDeclarationAndAssignment(string variableName,
548+
public static CSSyntax.VariableDeclarationSyntax CreateVariableDeclarationAndAssignment(string variableName,
528549
ExpressionSyntax initValue, TypeSyntax explicitType = null)
529550
{
530551
CSSyntax.VariableDeclaratorSyntax variableDeclaratorSyntax = CreateVariableDeclarator(variableName, initValue);

0 commit comments

Comments
 (0)