This commit is contained in:
GrahamTheCoder 2018-02-25 17:40:33 +00:00
Родитель 9b004e984d
Коммит a655bae331
1 изменённых файлов: 41 добавлений и 41 удалений

Просмотреть файл

@ -17,38 +17,38 @@ namespace ICSharpCode.CodeConverter.CSharp
public class ProjectConversion public class ProjectConversion
{ {
private bool _methodBodyOnly; private bool _methodBodyOnly;
private VisualBasicCompilation _compilation; private Compilation _sourceCompilation;
private IEnumerable<VisualBasicSyntaxTree> _syntaxTreesToConvert; private IEnumerable<SyntaxTree> _syntaxTreesToConvert;
private static readonly AdhocWorkspace AdhocWorkspace = new AdhocWorkspace(); private static readonly AdhocWorkspace AdhocWorkspace = new AdhocWorkspace();
private readonly ConcurrentDictionary<string, Exception> _errors = new ConcurrentDictionary<string, Exception>(); private readonly ConcurrentDictionary<string, Exception> _errors = new ConcurrentDictionary<string, Exception>();
private readonly Dictionary<string, SyntaxTree> _firstPassResults = new Dictionary<string, SyntaxTree>(); private readonly Dictionary<string, SyntaxTree> _firstPassResults = new Dictionary<string, SyntaxTree>();
private CSharpCompilation _cSharpCompilation; private Compilation _targetCompilation;
private ProjectConversion(VisualBasicCompilation compilation, string solutionDir) private ProjectConversion(Compilation sourceCompilation, string solutionDir)
: this(compilation, compilation.SyntaxTrees.OfType<VisualBasicSyntaxTree>().Where(t => t.FilePath.StartsWith(solutionDir))) : this(sourceCompilation, sourceCompilation.SyntaxTrees.Where(t => t.FilePath.StartsWith(solutionDir)))
{ {
} }
private ProjectConversion(VisualBasicCompilation compilation, IEnumerable<VisualBasicSyntaxTree> syntaxTreesToConvert) private ProjectConversion(Compilation sourceCompilation, IEnumerable<SyntaxTree> syntaxTreesToConvert)
{ {
_compilation = compilation; _sourceCompilation = sourceCompilation;
_syntaxTreesToConvert = syntaxTreesToConvert; _syntaxTreesToConvert = syntaxTreesToConvert;
} }
public static ConversionResult ConvertText(string text, IReadOnlyCollection<MetadataReference> references) public static ConversionResult ConvertText(string text, IReadOnlyCollection<MetadataReference> references)
{ {
var visualBasicSyntaxTree = CreateTree(text); var syntaxTree = CreateTree(text);
var compilation = CreateCompilationFromTree(visualBasicSyntaxTree, references); var compilation = CreateCompilationFromTree(syntaxTree, references);
return ConvertSingle(compilation, visualBasicSyntaxTree, new TextSpan(0, 0)).GetAwaiter().GetResult(); return ConvertSingle(compilation, syntaxTree, new TextSpan(0, 0)).GetAwaiter().GetResult();
} }
public static async Task<ConversionResult> ConvertSingle(VisualBasicCompilation compilation, VisualBasicSyntaxTree syntaxTree, TextSpan selected) public static async Task<ConversionResult> ConvertSingle(Compilation compilation, SyntaxTree syntaxTree, TextSpan selected)
{ {
var root = await syntaxTree.GetRootAsync(); var root = await syntaxTree.GetRootAsync();
if (selected.Length > 0) { if (selected.Length > 0) {
var annotatedSyntaxTree = GetSyntaxTreeWithAnnotatedSelection(selected, root); var annotatedSyntaxTree = GetSyntaxTreeWithAnnotatedSelection(selected, root);
compilation = compilation.ReplaceSyntaxTree(syntaxTree, annotatedSyntaxTree); compilation = compilation.ReplaceSyntaxTree(syntaxTree, annotatedSyntaxTree);
syntaxTree = (VisualBasicSyntaxTree) annotatedSyntaxTree; syntaxTree = annotatedSyntaxTree;
} }
var conversion = new ProjectConversion(compilation, new [] {syntaxTree}); var conversion = new ProjectConversion(compilation, new [] {syntaxTree});
@ -68,7 +68,7 @@ namespace ICSharpCode.CodeConverter.CSharp
var solutionDir = Path.GetDirectoryName(projects.First().Solution.FilePath); var solutionDir = Path.GetDirectoryName(projects.First().Solution.FilePath);
foreach (var project in projects) { foreach (var project in projects) {
var compilation = project.GetCompilationAsync().GetAwaiter().GetResult(); var compilation = project.GetCompilationAsync().GetAwaiter().GetResult();
var projectConversion = new ProjectConversion((VisualBasicCompilation)compilation, solutionDir); var projectConversion = new ProjectConversion(compilation, solutionDir);
foreach (var pathNodePair in projectConversion.Convert()) { foreach (var pathNodePair in projectConversion.Convert()) {
yield return new ConversionResult(pathNodePair.Value.ToFullString()) {SourcePathOrNull = pathNodePair.Key}; yield return new ConversionResult(pathNodePair.Value.ToFullString()) {SourcePathOrNull = pathNodePair.Key};
} }
@ -84,7 +84,7 @@ namespace ICSharpCode.CodeConverter.CSharp
private Dictionary<string, SyntaxNode> Convert() private Dictionary<string, SyntaxNode> Convert()
{ {
FirstPass(); FirstPass();
_cSharpCompilation = CSharpCompilation.Create("Conversion", _firstPassResults.Values, _compilation.References); _targetCompilation = CSharpCompilation.Create("Conversion", _firstPassResults.Values, _sourceCompilation.References);
var secondPassByFilePath = _firstPassResults.ToDictionary(cs => cs.Key, SingleSecondPass); var secondPassByFilePath = _firstPassResults.ToDictionary(cs => cs.Key, SingleSecondPass);
return secondPassByFilePath; return secondPassByFilePath;
} }
@ -99,7 +99,7 @@ namespace ICSharpCode.CodeConverter.CSharp
SingleFirstPass(tree, treeFilePath); SingleFirstPass(tree, treeFilePath);
} }
catch (NotImplementedOrRequiresSurroundingMethodDeclaration) catch (NotImplementedOrRequiresSurroundingMethodDeclaration)
when (!_methodBodyOnly && _compilation.SyntaxTrees.Length == 1) when (!_methodBodyOnly && _sourceCompilation.SyntaxTrees.Count() == 1)
{ {
SingleFirstPassSurroundedByClassAndMethod(tree); SingleFirstPassSurroundedByClassAndMethod(tree);
} }
@ -110,37 +110,15 @@ namespace ICSharpCode.CodeConverter.CSharp
} }
} }
private SyntaxNode SingleSecondPass(KeyValuePair<string, SyntaxTree> cs)
{
var secondPassNode = new CompilationErrorFixer(_cSharpCompilation, (CSharpSyntaxTree) cs.Value).Fix();
if (_methodBodyOnly) secondPassNode = secondPassNode.DescendantNodes().OfType<MethodDeclarationSyntax>().First().Body;
return Formatter.Format(secondPassNode, AdhocWorkspace);
}
private void SingleFirstPass(VisualBasicSyntaxTree tree, string treeFilePath)
{
var converted = VisualBasicConverter.ConvertCompilationTree(_compilation, tree);
_firstPassResults.Add(treeFilePath, SyntaxFactory.SyntaxTree(converted));
}
private void SingleFirstPassSurroundedByClassAndMethod(SyntaxTree tree) private void SingleFirstPassSurroundedByClassAndMethod(SyntaxTree tree)
{ {
var newTree = CreateTree(WithSurroundingClassAndMethod(tree.GetText().ToString())); var newTree = CreateTree(WithSurroundingClassAndMethod(tree.GetText().ToString()));
_methodBodyOnly = true; _methodBodyOnly = true;
_compilation = _compilation.AddSyntaxTrees(newTree); _sourceCompilation = _sourceCompilation.AddSyntaxTrees(newTree);
_syntaxTreesToConvert = new[] {newTree}; _syntaxTreesToConvert = new[] {newTree};
Convert(); Convert();
} }
private static string WithSurroundingClassAndMethod(string text)
{
return $@"Class SurroundingClass
Sub SurroundingSub()
{text}
End Sub
End Class";
}
private static SyntaxTree GetSyntaxTreeWithAnnotatedSelection(TextSpan selected, SyntaxNode root) private static SyntaxTree GetSyntaxTreeWithAnnotatedSelection(TextSpan selected, SyntaxNode root)
{ {
var selectedNode = root.FindNode(selected); var selectedNode = root.FindNode(selected);
@ -154,12 +132,34 @@ End Class";
return annotatedNode == null ? resultNode : Formatter.Format(annotatedNode, AdhocWorkspace); return annotatedNode == null ? resultNode : Formatter.Format(annotatedNode, AdhocWorkspace);
} }
private static VisualBasicSyntaxTree CreateTree(string text) private void SingleFirstPass(SyntaxTree tree, string treeFilePath)
{ {
return (VisualBasicSyntaxTree) Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseSyntaxTree(SourceText.From(text)); var converted = VisualBasicConverter.ConvertCompilationTree((VisualBasicCompilation)_sourceCompilation, (VisualBasicSyntaxTree)tree);
_firstPassResults.Add(treeFilePath, SyntaxFactory.SyntaxTree(converted));
} }
private static VisualBasicCompilation CreateCompilationFromTree(VisualBasicSyntaxTree tree, IEnumerable<MetadataReference> references) private SyntaxNode SingleSecondPass(KeyValuePair<string, SyntaxTree> cs)
{
var secondPassNode = new CompilationErrorFixer((CSharpCompilation)_targetCompilation, (CSharpSyntaxTree)cs.Value).Fix();
if (_methodBodyOnly) secondPassNode = secondPassNode.DescendantNodes().OfType<MethodDeclarationSyntax>().First().Body;
return Formatter.Format(secondPassNode, AdhocWorkspace);
}
private static string WithSurroundingClassAndMethod(string text)
{
return $@"Class SurroundingClass
Sub SurroundingSub()
{text}
End Sub
End Class";
}
private static SyntaxTree CreateTree(string text)
{
return Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseSyntaxTree(SourceText.From(text));
}
private static Compilation CreateCompilationFromTree(SyntaxTree tree, IEnumerable<MetadataReference> references)
{ {
var compilationOptions = new VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary) var compilationOptions = new VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
.WithRootNamespace("TestProject") .WithRootNamespace("TestProject")