Skip to content

Commit

Permalink
Merge pull request #539 from icsharpcode/fix-test-compile-errors
Browse files Browse the repository at this point in the history
Fix test compile errors
  • Loading branch information
GrahamTheCoder authored Mar 11, 2020
2 parents b4f84d2 + fe85a41 commit 6e5b036
Show file tree
Hide file tree
Showing 53 changed files with 3,014 additions and 2,366 deletions.
10 changes: 0 additions & 10 deletions CodeConverter/CSharp/CachedReflectedDelegates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,6 @@ namespace ICSharpCode.CodeConverter.CSharp
/// </remarks>
internal static class CachedReflectedDelegates
{
/// <summary>
/// This method becomes public in CodeAnalysis 3.1 and hence we can be confident it won't disappear.
/// Need to use reflection for now until that version is widely enough deployed as taking a dependency would mean everyone needs latest VS version.
/// </summary>
public static readonly Lazy<Func<CompilationOptions, byte, CompilationOptions>> LazyWithMetadataImportOptions =
new Lazy<Func<CompilationOptions, byte, CompilationOptions>>(() => typeof(CompilationOptions)
.GetMethod("WithMetadataImportOptions",
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
.CreateOpenInstanceDelegateForcingType<CompilationOptions, byte, CompilationOptions>());

public static bool IsMyGroupCollectionProperty(this IPropertySymbol declaredSymbol) =>
GetCachedReflectedPropertyDelegate(declaredSymbol, "IsMyGroupCollectionProperty", ref _isMyGroupCollectionProperty);
private static Func<ISymbol, bool> _isMyGroupCollectionProperty;
Expand Down
23 changes: 15 additions & 8 deletions CodeConverter/CSharp/ExpressionNodeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,13 @@ public override async Task<CSharpSyntaxNode> VisitSimpleArgument(VBasic.Syntax.S

public override async Task<CSharpSyntaxNode> VisitNameOfExpression(VBasic.Syntax.NameOfExpressionSyntax node)
{
return SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("nameof"), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument((ExpressionSyntax) await node.Argument.AcceptAsync(TriviaConvertingExpressionVisitor)))));
return SyntaxFactory.InvocationExpression(NameOf(), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList<ArgumentSyntax>(SyntaxFactory.Argument((ExpressionSyntax)await node.Argument.AcceptAsync(TriviaConvertingExpressionVisitor)))));
}

private static ExpressionSyntax NameOf()
{
// Usually it'd be preferable to just construct the Identifier ourselves, but the opportunity to inject parse options lets us control the LanguageVersion which needs to be high enough not to consider nameof an error
return SyntaxFactory.ParseExpression("nameof", options: CSharpCompiler.ParseOptions);
}

public override async Task<CSharpSyntaxNode> VisitEqualsValue(VBasic.Syntax.EqualsValueSyntax node)
Expand Down Expand Up @@ -486,10 +492,8 @@ public override async Task<CSharpSyntaxNode> VisitArrayCreationExpression(VBasic
{
var bounds = await CommonConversions.ConvertArrayRankSpecifierSyntaxes(node.RankSpecifiers, node.ArrayBounds);

var allowInitializer = node.Initializer.Initializers.Any()
|| node.RankSpecifiers.Any()
|| node.ArrayBounds == null
|| (node.Initializer.Initializers.Any() && node.ArrayBounds.Arguments.All(b => b.IsOmitted || _semanticModel.GetConstantValue(b.GetExpression()).HasValue));
var allowInitializer = node.ArrayBounds?.Arguments.Any() != true ||
node.Initializer.Initializers.Any() && node.ArrayBounds.Arguments.All(b => b.IsOmitted || _semanticModel.GetConstantValue(b.GetExpression()).HasValue);

var initializerToConvert = allowInitializer ? node.Initializer : null;
return SyntaxFactory.ArrayCreationExpression(
Expand All @@ -507,15 +511,18 @@ public override async Task<CSharpSyntaxNode> VisitCollectionInitializer(VBasic.S
var initializers = (await node.Initializers.SelectAsync(i => i.AcceptAsync(TriviaConvertingExpressionVisitor))).Cast<ExpressionSyntax>();
var initializer = SyntaxFactory.InitializerExpression(initializerKind, SyntaxFactory.SeparatedList(initializers));
if (isExplicitCollectionInitializer) return initializer;

if (!initializers.Any() && _semanticModel.GetTypeInfo(node).ConvertedType is IArrayTypeSymbol arrayType) {

if (!(_semanticModel.GetTypeInfo(node).ConvertedType is IArrayTypeSymbol arrayType)) return SyntaxFactory.ImplicitArrayCreationExpression(initializer);

if (!initializers.Any()) {

var arrayTypeArgs = SyntaxFactory.TypeArgumentList(SyntaxFactory.SingletonSeparatedList(CommonConversions.GetTypeSyntax(arrayType.ElementType)));
var arrayEmpty = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
SyntaxFactory.IdentifierName(nameof(Array)), SyntaxFactory.GenericName(nameof(Array.Empty)).WithTypeArgumentList(arrayTypeArgs));
return SyntaxFactory.InvocationExpression(arrayEmpty);
}
return SyntaxFactory.ImplicitArrayCreationExpression(initializer);
var commas = Enumerable.Repeat(SyntaxFactory.Token(SyntaxKind.CommaToken), arrayType.Rank - 1);
return SyntaxFactory.ImplicitArrayCreationExpression(SyntaxFactory.TokenList(commas), initializer);
}

public override async Task<CSharpSyntaxNode> VisitQueryExpression(VBasic.Syntax.QueryExpressionSyntax node)
Expand Down
12 changes: 6 additions & 6 deletions CodeConverter/CSharp/ProjectExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ internal static class ProjectExtensions
{
private static char[] DirSeparators = new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };

public static Project CreateReferenceOnlyProjectFromAnyOptions(this Project project, CompilationOptions baseOptions)
public static Project CreateReferenceOnlyProjectFromAnyOptions(this Project project, CompilationOptions baseOptions, ParseOptions parseOptions)
{
var options = baseOptions.WithMetadataImportOptionsAll();
var options = baseOptions.WithMetadataImportOptions(MetadataImportOptions.All);
var viewerId = ProjectId.CreateNewId();
var projectReferences = project.ProjectReferences.Concat(new[] {new ProjectReference(project.Id)});
var viewerProjectInfo = project.ToProjectInfo(viewerId, project.Name + viewerId, options,
projectReferences);
projectReferences, parseOptions);
var csharpViewOfVbProject = project.Solution.AddProject(viewerProjectInfo).GetProject(viewerId);
return csharpViewOfVbProject;
}
Expand Down Expand Up @@ -70,10 +70,10 @@ public static (Project project, List<WipFileConversion<DocumentId>> firstPassDoc
DocumentId docId = null;
if (firstPassResult.Wip != null)
{
var document = project.AddDocument(firstPassResult.Path, firstPassResult.Wip,
docId = DocumentId.CreateNewId(project.Id);
var solution = project.Solution.AddDocument(docId, firstPassResult.Path, firstPassResult.Wip,
filePath: firstPassResult.Path);
project = document.Project;
docId = document.Id;
project = solution.GetProject(project.Id);
}

return WipFileConversion.Create(firstPassResult.Path, docId, firstPassResult.Errors);
Expand Down
18 changes: 9 additions & 9 deletions CodeConverter/CSharp/ProjectMergedDeclarationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.Rename;
using Microsoft.CodeAnalysis.VisualBasic;
using System.Threading;
using System.Collections.Generic;

namespace ICSharpCode.CodeConverter.CSharp
{
Expand All @@ -26,11 +27,12 @@ public static async Task<Project> WithRenamedMergedMyNamespace(this Project vbPr
var projectDir = Path.Combine(vbProject.GetDirectoryPath(), "My Project");

var compilation = await vbProject.GetCompilationAsync(cancellationToken);
string embeddedSourceText = (await GetAllEmbeddedSourceText(compilation));
string generatedSourceText = (await GetDynamicallyGeneratedSourceText(compilation));
var embeddedSourceTexts = await GetAllEmbeddedSourceText(compilation).Select((r, i) => (Text: r, Suffix: $".Static.{i+1}")).ToArrayAsync();
var generatedSourceTexts = (Text: await GetDynamicallyGeneratedSourceText(compilation), Suffix: ".Dynamic").Yield();

vbProject = WithRenamespacedDocument(name + ".Static", vbProject, embeddedSourceText, projectDir);
vbProject = WithRenamespacedDocument(name + ".Dynamic", vbProject, generatedSourceText, projectDir);
foreach (var (text, suffix) in embeddedSourceTexts.Concat(generatedSourceTexts)) {
vbProject = WithRenamespacedDocument(name + suffix, vbProject, text, projectDir);
}

return vbProject;
}
Expand All @@ -41,15 +43,12 @@ private static Project WithRenamespacedDocument(string baseName, Project vbProje
return vbProject.AddDocument(baseName, sourceText.Renamespace(), filePath: Path.Combine(myProjectDirPath, baseName + ".Designer.vb")).Project;
}

private static async Task<string> GetAllEmbeddedSourceText(Compilation compilation)
private static async IAsyncEnumerable<string> GetAllEmbeddedSourceText(Compilation compilation)
{
var roots = await compilation.SourceModule.GlobalNamespace.Locations.
Where(l => !l.IsInSource).Select(CachedReflectedDelegates.GetEmbeddedSyntaxTree)
.SelectAsync(t => t.GetTextAsync());
var renamespacesRootTexts =
roots.Select(r => r.ToString());
var combined = string.Join(Environment.NewLine, renamespacesRootTexts);
return combined;
foreach (var r in roots) yield return r.ToString();
}

private static async Task<string> GetDynamicallyGeneratedSourceText(Compilation compilation)
Expand Down Expand Up @@ -109,6 +108,7 @@ private static string Renamespace(this string sourceText)
{
return sourceText
.Replace("Namespace Global.Microsoft.VisualBasic", $"Namespace Global.Microsoft.{Constants.MergedMsVbNamespace}")
.Replace("Global.Microsoft.VisualBasic.Embedded", $"Global.Microsoft.{Constants.MergedMsVbNamespace}.Embedded")
.Replace("Namespace My", $"Namespace {Constants.MergedMyNamespace}");
}

Expand Down
12 changes: 2 additions & 10 deletions CodeConverter/CSharp/VBToCSProjectContentsConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@ internal class VBToCSProjectContentsConverter : IProjectContentsConverter
private CSharpCompilation _csharpViewOfVbSymbols;
private Project _convertedCsProject;

/// <summary>
/// It's really hard to change simplifier options since everything is done on the Object hashcode of internal fields.
/// I wanted to avoid saying "default" instead of "default(string)" because I don't want to force a later language version on people in such a common case.
/// This will have that effect, but also has the possibility of failing to interpret code output by this converter.
/// If this has such unintended effects in future, investigate the code that loads options from an editorconfig file
/// </summary>
private static readonly CSharpParseOptions DoNotAllowImplicitDefault = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7);

private Project _csharpReferenceProject;
private readonly IProgress<ConversionProgress> _progress;
private readonly CancellationToken _cancellationToken;
Expand All @@ -45,8 +37,8 @@ public VBToCSProjectContentsConverter(ConversionOptions conversionOptions, IProg
public async Task InitializeSourceAsync(Project project)
{
var cSharpCompilationOptions = CSharpCompiler.CreateCompilationOptions();
_convertedCsProject = project.ToProjectFromAnyOptions(cSharpCompilationOptions, DoNotAllowImplicitDefault);
_csharpReferenceProject = project.CreateReferenceOnlyProjectFromAnyOptions(cSharpCompilationOptions);
_convertedCsProject = project.ToProjectFromAnyOptions(cSharpCompilationOptions, CSharpCompiler.ParseOptions);
_csharpReferenceProject = project.CreateReferenceOnlyProjectFromAnyOptions(cSharpCompilationOptions, CSharpCompiler.ParseOptions);
_csharpViewOfVbSymbols = (CSharpCompilation) await _csharpReferenceProject.GetCompilationAsync(_cancellationToken);
Project = await project.WithRenamedMergedMyNamespace(_cancellationToken);
}
Expand Down
2 changes: 1 addition & 1 deletion CodeConverter/ConversionResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public string GetExceptionsAsString()
public void WriteToFile()
{
Directory.CreateDirectory(Path.GetDirectoryName(TargetPathOrNull));
File.WriteAllText(TargetPathOrNull, ConvertedCode, Encoding.UTF8);
File.WriteAllText(TargetPathOrNull, ConvertedCode ?? GetExceptionsAsString(), Encoding.UTF8);
}
}
}
5 changes: 0 additions & 5 deletions CodeConverter/Shared/CompilationOptionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,5 @@ public static Document CreateProjectDocumentFromTree(this CompilationOptions opt
.WithMetadataReferences(references);
return project.AddDocument("CodeToConvert", tree.GetRoot(), filePath: Path.Combine(Directory.GetCurrentDirectory(), "TempCodeToConvert.txt"));
}

public static CompilationOptions WithMetadataImportOptionsAll(this CompilationOptions baseOptions)
{
return CachedReflectedDelegates.LazyWithMetadataImportOptions.Value(baseOptions, 2 /*MetadataImportOptions.All*/);
}
}
}
18 changes: 7 additions & 11 deletions CodeConverter/Shared/ProjectConversion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,19 @@ public class ProjectConversion
{
private readonly IReadOnlyCollection<Document> _documentsToConvert;
private readonly ILanguageConversion _languageConversion;
private readonly bool _showCompilationErrors =
#if DEBUG && ShowCompilationErrors
true;
#else
false;
#endif
private readonly bool _showCompilationErrors;
private readonly bool _returnSelectedNode;
private static readonly string[] BannedPaths = new[] { ".AssemblyAttributes.", "\\bin\\", "\\obj\\" };
private readonly IProjectContentsConverter _projectContentsConverter;
private readonly CancellationToken _cancellationToken;

private ProjectConversion(IProjectContentsConverter projectContentsConverter, IEnumerable<Document> documentsToConvert,
ILanguageConversion languageConversion, CancellationToken cancellationToken, bool returnSelectedNode = false)
ILanguageConversion languageConversion, CancellationToken cancellationToken, bool showCompilationErrors, bool returnSelectedNode = false)
{
_projectContentsConverter = projectContentsConverter;
_languageConversion = languageConversion;
_documentsToConvert = documentsToConvert.ToList();
_showCompilationErrors = showCompilationErrors;
_returnSelectedNode = returnSelectedNode;
_cancellationToken = cancellationToken;
}
Expand Down Expand Up @@ -69,7 +65,7 @@ private ProjectConversion(IProjectContentsConverter projectContentsConverter, IE

document = projectContentsConverter.Project.GetDocument(document.Id);

var conversion = new ProjectConversion(projectContentsConverter, new[] { document }, languageConversion, cancellationToken, returnSelectedNode);
var conversion = new ProjectConversion(projectContentsConverter, new[] { document }, languageConversion, cancellationToken, conversionOptions.ShowCompilationErrors, returnSelectedNode);
var conversionResults = await conversion.Convert(progress).ToArrayAsync();
var codeResult = conversionResults.SingleOrDefault(x => !string.IsNullOrWhiteSpace(x.ConvertedCode))
?? conversionResults.First();
Expand Down Expand Up @@ -154,7 +150,7 @@ private static async IAsyncEnumerable<ConversionResult> ConvertProjectContents(
//Perf heuristic: Decrease memory pressure on the simplification phase by converting large files first https://github.com/icsharpcode/CodeConverter/issues/524#issuecomment-590301594
var documentsToConvert = documentsWithLengths.OrderByDescending(d => d.Length).Select(d => d.Doc);

var projectConversion = new ProjectConversion(projectContentsConverter, documentsToConvert, languageConversion, cancellationToken);
var projectConversion = new ProjectConversion(projectContentsConverter, documentsToConvert, languageConversion, cancellationToken, false);

var results = projectConversion.Convert(progress);
await foreach (var result in results) yield return result;
Expand All @@ -168,8 +164,8 @@ private async IAsyncEnumerable<ConversionResult> Convert(IProgress<ConversionPro
var (proj1, docs1) = await _projectContentsConverter.GetConvertedProject(await firstPassResults.ToArrayAsync());

var warnings = await GetProjectWarnings(_projectContentsConverter.Project, proj1);
if (warnings != null) {
var warningPath = Path.Combine(proj1.GetDirectoryPath(), "ConversionWarnings.txt");
if (!string.IsNullOrWhiteSpace(warnings)) {
var warningPath = Path.Combine(_projectContentsConverter.Project.GetDirectoryPath(), "ConversionWarnings.txt");
yield return new ConversionResult() { SourcePathOrNull = warningPath, Exceptions = new[] { warnings } };
}

Expand Down
1 change: 1 addition & 0 deletions CodeConverter/Shared/SingleConversionOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ namespace ICSharpCode.CodeConverter.Shared
public class SingleConversionOptions : ConversionOptions
{
public TextSpan SelectedTextSpan { get; set; } = new TextSpan();
internal bool ShowCompilationErrors { get; set; }
}
}
6 changes: 4 additions & 2 deletions CodeConverter/Util/CSharpCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class CSharpCompiler : ICompiler

public SyntaxTree CreateTree(string text)
{
return SyntaxFactory.ParseSyntaxTree(text, encoding: Encoding.UTF8);
return SyntaxFactory.ParseSyntaxTree(text, ParseOptions, encoding: Encoding.UTF8);
}

public Compilation CreateCompilationFromTree(SyntaxTree tree, IEnumerable<MetadataReference> references)
Expand All @@ -34,7 +34,9 @@ private static CSharpCompilation CreateCSharpCompilation()

public static CSharpCompilationOptions CreateCompilationOptions()
{
return new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
return new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true);
}

public static CSharpParseOptions ParseOptions { get; } = new CSharpParseOptions(LanguageVersion.Latest);
}
}
3 changes: 2 additions & 1 deletion CodeConverter/Util/CompilationWarnings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public static string WarningsForCompilation(Compilation finalCompilation, string
{
var targetErrors = GetDiagnostics(finalCompilation);
return targetErrors.Any()
? $"{targetErrors.Count} {compilationDescription} compilation errors:{Environment.NewLine}{String.Join(Environment.NewLine, targetErrors)}"
? $"{Environment.NewLine}{targetErrors.Count} {compilationDescription} compilation errors:{Environment.NewLine}{String.Join(Environment.NewLine, targetErrors)}"
: null;
}

Expand All @@ -20,6 +20,7 @@ private static List<string> GetDiagnostics(Compilation compilation)
var diagnostics = compilation.GetDiagnostics()
.Where(d => d.Severity == DiagnosticSeverity.Error)
.Select(d => $"{d.Id}: {d.GetMessage()}")
.Distinct()
.ToList();
return diagnostics;
}
Expand Down
4 changes: 3 additions & 1 deletion CodeConverter/Util/VisualBasicCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public VisualBasicCompiler(string rootNamespace)

public SyntaxTree CreateTree(string text)
{
return SyntaxFactory.ParseSyntaxTree(text, encoding: Encoding.UTF8);
return SyntaxFactory.ParseSyntaxTree(text, ParseOptions, encoding: Encoding.UTF8);
}

public Compilation CreateCompilationFromTree(SyntaxTree tree, IEnumerable<MetadataReference> references)
Expand Down Expand Up @@ -75,5 +75,7 @@ public static VisualBasicCompilationOptions CreateCompilationOptions(string root
.WithRootNamespace(rootNamespace);
return compilationOptions;
}

public static VisualBasicParseOptions ParseOptions { get; } = new VisualBasicParseOptions(LanguageVersion.Latest);
}
}
Loading

0 comments on commit 6e5b036

Please sign in to comment.