Separate language specifics
This commit is contained in:
Родитель
9b004e984d
Коммит
a655bae331
|
@ -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")
|
||||||
|
|
Загрузка…
Ссылка в новой задаче