Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# Change Log
All notable changes to the code converter will be documented here.

# 6.5.0 TBC
# 6.6.0 TBC

### C# -> VB
* Improve event identifier conversion

# 6.5.0 03/03/2019
* Avoid fatal error converting a project in a solution containing a website project (#243)
* Improve best-effort conversion in the presence of errors
* Improved nuget package and web converter's snippet detection
Expand Down
16 changes: 8 additions & 8 deletions ICSharpCode.CodeConverter/Shared/ProjectConversion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ public class ProjectConversion
{
private readonly Compilation _sourceCompilation;
private readonly IEnumerable<SyntaxTree> _syntaxTreesToConvert;
// ReSharper disable once StaticMemberInGenericType - Stateless
private static readonly AdhocWorkspace AdhocWorkspace = new AdhocWorkspace();
private readonly ConcurrentDictionary<string, string> _errors = new ConcurrentDictionary<string, string>();
private readonly Dictionary<string, SyntaxTree> _firstPassResults = new Dictionary<string, SyntaxTree>();
private readonly ILanguageConversion _languageConversion;
Expand Down Expand Up @@ -147,12 +145,13 @@ private Dictionary<string, SyntaxNode> Convert()
private Dictionary<string, SyntaxNode> SecondPass()
{
var secondPassByFilePath = new Dictionary<string, SyntaxNode>();
var adhocWorkspace = new AdhocWorkspace();
foreach (var firstPassResult in _firstPassResults) {
var treeFilePath = firstPassResult.Key;
try {
secondPassByFilePath.Add(treeFilePath, SingleSecondPass(firstPassResult));
secondPassByFilePath.Add(treeFilePath, SingleSecondPass(firstPassResult, adhocWorkspace));
} catch (Exception e) {
secondPassByFilePath.Add(treeFilePath, Format(firstPassResult.Value.GetRoot()));
secondPassByFilePath.Add(treeFilePath, Format(firstPassResult.Value.GetRoot(), adhocWorkspace));
_errors.TryAdd(treeFilePath, e.ToString());
}
}
Expand All @@ -169,10 +168,10 @@ private void AddProjectWarnings()
}
}

private SyntaxNode SingleSecondPass(KeyValuePair<string, SyntaxTree> cs)
private SyntaxNode SingleSecondPass(KeyValuePair<string, SyntaxTree> cs, AdhocWorkspace workspace)
{
var secondPassNode = _languageConversion.SingleSecondPass(cs);
return Format(secondPassNode);
return Format(secondPassNode, workspace);
}

private void FirstPass()
Expand Down Expand Up @@ -237,10 +236,11 @@ private static async Task<SyntaxTree> GetSyntaxTreeWithAnnotatedSelection(Syntax
return root.WithAnnotatedNode(selectedNode, AnnotationConstants.SelectedNodeAnnotationKind);
}

private SyntaxNode Format(SyntaxNode resultNode)
private SyntaxNode Format(SyntaxNode resultNode, Workspace workspace)
{
SyntaxNode selectedNode = _handlePartialConversion ? GetSelectedNode(resultNode) : resultNode;
return Formatter.Format(selectedNode ?? resultNode, AdhocWorkspace);
SyntaxNode nodeToFormat = selectedNode ?? resultNode;
return Formatter.Format(nodeToFormat, workspace);
}

private SyntaxNode GetSelectedNode(SyntaxNode resultNode)
Expand Down
48 changes: 41 additions & 7 deletions ICSharpCode.CodeConverter/VB/CommonConversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.CodeAnalysis.VisualBasic.Syntax;
using AttributeListSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.AttributeListSyntax;
using BinaryExpressionSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.BinaryExpressionSyntax;
using CSharpExtensions = Microsoft.CodeAnalysis.CSharp.CSharpExtensions;
using CSSyntaxKind = Microsoft.CodeAnalysis.CSharp.SyntaxKind;
using ExpressionSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax;
Expand Down Expand Up @@ -206,7 +207,7 @@ public ExpressionSyntax ReduceArrayUpperBoundExpression(Microsoft.CodeAnalysis.C

public LambdaExpressionSyntax ConvertLambdaExpression(AnonymousFunctionExpressionSyntax node, CSharpSyntaxNode body, IEnumerable<ParameterSyntax> parameters, SyntaxTokenList modifiers)
{
var symbol = ModelExtensions.GetSymbolInfo(_semanticModel, node).Symbol as IMethodSymbol;
var symbol = (IMethodSymbol) ModelExtensions.GetSymbolInfo(_semanticModel, node).Symbol;
var parameterList = SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(parameters.Select(p => (Microsoft.CodeAnalysis.VisualBasic.Syntax.ParameterSyntax)p.Accept(_nodesVisitor))));
LambdaHeaderSyntax header;
EndBlockStatementSyntax endBlock;
Expand All @@ -233,7 +234,8 @@ public LambdaExpressionSyntax ConvertLambdaExpression(AnonymousFunctionExpressio
var vbThrowExpression = (ExpressionSyntax)csThrowExpression.Expression.Accept(_nodesVisitor);
var vbThrowStatement = SyntaxFactory.ThrowStatement(SyntaxFactory.Token(SyntaxKind.ThrowKeyword), vbThrowExpression);

return SyntaxFactory.MultiLineFunctionLambdaExpression(header, SyntaxFactory.SingletonList<StatementSyntax>(vbThrowStatement), endBlock);
return SyntaxFactory.MultiLineFunctionLambdaExpression(header,
SyntaxFactory.SingletonList<StatementSyntax>(vbThrowStatement), endBlock);
} else {
statements = InsertRequiredDeclarations(
SyntaxFactory.SingletonList<StatementSyntax>(
Expand Down Expand Up @@ -396,19 +398,25 @@ public VisualBasicSyntaxNode ConvertTopLevelExpression(Microsoft.CodeAnalysis.CS
return topLevelExpression.Accept(_nodesVisitor);
}

private static ModifiedIdentifierSyntax ExtractIdentifier(Microsoft.CodeAnalysis.CSharp.Syntax.VariableDeclaratorSyntax v)
private ModifiedIdentifierSyntax ExtractIdentifier(Microsoft.CodeAnalysis.CSharp.Syntax.VariableDeclaratorSyntax v)
{
return SyntaxFactory.ModifiedIdentifier(ConvertIdentifier(v.Identifier));
}

public static SyntaxToken ConvertIdentifier(SyntaxToken id)
public SyntaxToken ConvertIdentifier(SyntaxToken id)
{
var idText = id.ValueText;
CSharpSyntaxNode parent = (CSharpSyntaxNode) id.Parent;
var idText = IsEventHandlerIdentifier(parent) && !IsEventHandlerAssignLhs(parent) ? id.ValueText + "Event" : id.ValueText;
// Underscore is a special character in VB lexer which continues lines - not sure where to find the whole set of other similar tokens if any
// Rather than a complicated contextual rename, just add an extra dash to all identifiers and hope this method is consistently used
bool keywordRequiresEscaping = KeywordRequiresEscaping(id);
return Identifier(idText, keywordRequiresEscaping);
}

public static SyntaxToken Identifier(string idText, bool keywordRequiresEscaping = false)
{
if (idText.All(c => c == '_')) idText += "_";

return KeywordRequiresEscaping(id) ? SyntaxFactory.Identifier($"[{idText}]") : SyntaxFactory.Identifier(idText);
return keywordRequiresEscaping ? SyntaxFactory.Identifier($"[{idText}]") : SyntaxFactory.Identifier(idText);
}

private static bool KeywordRequiresEscaping(SyntaxToken id)
Expand Down Expand Up @@ -530,5 +538,31 @@ private static string UppercaseFirstLetter(string sourceText)
{
return sourceText.Substring(0, 1).ToUpper() + sourceText.Substring(1);
}

public bool IsEventHandlerIdentifier(CSharpSyntaxNode syntax)
{
return GetSymbol(syntax).IsKind(SymbolKind.Event);
}

private static bool IsEventHandlerAssignLhs(CSharpSyntaxNode syntax)
{
var assignmentExpressionSyntax = syntax.GetAncestor<AssignmentExpressionSyntax>();
return assignmentExpressionSyntax != null && assignmentExpressionSyntax.IsKind(CSSyntaxKind.AddAssignmentExpression, CSSyntaxKind.SubtractAssignmentExpression)
&& assignmentExpressionSyntax.Left.DescendantNodes().Contains(syntax);
}

private ISymbol GetSymbol(CSharpSyntaxNode syntax)
{
return syntax.SyntaxTree == _semanticModel.SyntaxTree
? _semanticModel.GetSymbolInfo(syntax).Symbol
: null;
}

private ITypeSymbol GetTypeSymbol(CSharpSyntaxNode syntax)
{
return syntax.SyntaxTree == _semanticModel.SyntaxTree
? _semanticModel.GetTypeInfo(syntax).Type
: null;
}
}
}
Loading