提交 e8dde0d9 编写于 作者: H Heejae Chang

Merge branch 'master' of https://github.com/dotnet/roslyn into oop2


Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysisTest", "src\Compilers\Core\CodeAnalysisTest\CodeAnalysisTest.csproj", "{A4C99B85-765C-4C65-9C2A-BB609AAB09E6}"
EndProject
......@@ -135,22 +135,22 @@ Global
src\Test\Utilities\Shared\TestUtilities.projitems*{6ff42825-5464-4151-ac55-ed828168c192}*SharedItemsImports = 13
src\Compilers\Core\CommandLine\CommandLine.projitems*{ad6f474e-e6d4-4217-91f3-b7af1be31ccc}*SharedItemsImports = 13
src\Compilers\Core\AnalyzerDriver\AnalyzerDriver.projitems*{d0bc9be7-24f6-40ca-8dc6-fcb93bd44b34}*SharedItemsImports = 13
src\Compilers\Server\ServerShared\ServerShared.projitems*{06b26dcb-7a12-48ef-ae50-708593abd05f}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{06b26dcb-7a12-48ef-ae50-708593abd05f}*SharedItemsImports = 4
src\Compilers\Server\ServerShared\ServerShared.projitems*{06b26dcb-7a12-48ef-ae50-708593abd05f}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{e58ee9d7-1239-4961-a0c1-f9ec3952c4c1}*SharedItemsImports = 4
src\Compilers\Server\ServerShared\ServerShared.projitems*{9508f118-f62e-4c16-a6f4-7c3b56e166ad}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{9508f118-f62e-4c16-a6f4-7c3b56e166ad}*SharedItemsImports = 4
src\Compilers\Server\ServerShared\ServerShared.projitems*{9508f118-f62e-4c16-a6f4-7c3b56e166ad}*SharedItemsImports = 4
src\Compilers\Core\SharedCollections\SharedCollections.projitems*{afde6bea-5038-4a4a-a88e-dbd2e4088eed}*SharedItemsImports = 4
src\Compilers\Core\AnalyzerDriver\AnalyzerDriver.projitems*{1ee8cad3-55f9-4d91-96b2-084641da9a6c}*SharedItemsImports = 4
src\Compilers\Core\SharedCollections\SharedCollections.projitems*{1ee8cad3-55f9-4d91-96b2-084641da9a6c}*SharedItemsImports = 4
src\Compilers\Core\MSBuildTask\Shared\MSBuildTask.Shared.projitems*{7ad4fe65-9a30-41a6-8004-aa8f89bcb7f3}*SharedItemsImports = 4
src\Compilers\Core\AnalyzerDriver\AnalyzerDriver.projitems*{1ee8cad3-55f9-4d91-96b2-084641da9a6c}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{7ad4fe65-9a30-41a6-8004-aa8f89bcb7f3}*SharedItemsImports = 4
src\Compilers\Core\MSBuildTask\Shared\MSBuildTask.Shared.projitems*{7ad4fe65-9a30-41a6-8004-aa8f89bcb7f3}*SharedItemsImports = 4
src\Compilers\CSharp\CSharpAnalyzerDriver\CSharpAnalyzerDriver.projitems*{b501a547-c911-4a05-ac6e-274a50dff30e}*SharedItemsImports = 4
src\Compilers\VisualBasic\BasicAnalyzerDriver\BasicAnalyzerDriver.projitems*{2523d0e6-df32-4a3e-8ae0-a19bffae2ef6}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{4b45ca0c-03a0-400f-b454-3d4bcb16af38}*SharedItemsImports = 4
src\Compilers\Core\SharedCollections\SharedCollections.projitems*{c1930979-c824-496b-a630-70f5369a636f}*SharedItemsImports = 13
src\Compilers\Core\MSBuildTask\Shared\MSBuildTask.Shared.projitems*{d874349c-8bb3-4bdc-8535-2d52ccca1198}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{d874349c-8bb3-4bdc-8535-2d52ccca1198}*SharedItemsImports = 4
src\Compilers\Core\MSBuildTask\Shared\MSBuildTask.Shared.projitems*{d874349c-8bb3-4bdc-8535-2d52ccca1198}*SharedItemsImports = 4
src\Compilers\Core\CommandLine\CommandLine.projitems*{e3cd2895-76a8-4d11-a316-ea67cb5ea42c}*SharedItemsImports = 4
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
......
......@@ -2,6 +2,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Editing;
......@@ -25,7 +26,7 @@ internal abstract class AbstractMemberInsertingCompletionProvider : CompletionLi
protected abstract SyntaxToken GetToken(MemberInsertionCompletionItem completionItem, SyntaxTree tree, CancellationToken cancellationToken);
protected abstract ISymbol GenerateMember(ISymbol member, INamedTypeSymbol containingType, Document document, MemberInsertionCompletionItem item, CancellationToken cancellationToken);
protected abstract Task<ISymbol> GenerateMemberAsync(ISymbol member, INamedTypeSymbol containingType, Document document, MemberInsertionCompletionItem item, CancellationToken cancellationToken);
protected abstract int GetTargetCaretPosition(SyntaxNode caretTarget);
protected abstract SyntaxNode GetSyntax(SyntaxToken commonSyntaxToken);
......@@ -44,12 +45,13 @@ public void Commit(CompletionItem completionItem, ITextView textView, ITextBuffe
allowCancel: true,
action: c =>
{
var newDocument = DetermineNewDocument((MemberInsertionCompletionItem)completionItem, currentSnapshot, c.CancellationToken);
var cancellationToken = c.CancellationToken;
var newDocument = DetermineNewDocumentAsync((MemberInsertionCompletionItem)completionItem, currentSnapshot, cancellationToken).WaitAndGetResult(cancellationToken);
// Apply the new document to workspace
newDocument.Project.Solution.Workspace.ApplyDocumentChanges(newDocument, c.CancellationToken);
newDocument.Project.Solution.Workspace.ApplyDocumentChanges(newDocument, cancellationToken);
var newRoot = newDocument.GetSyntaxRootAsync(c.CancellationToken).WaitAndGetResult(c.CancellationToken);
var newRoot = newDocument.GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken);
// Attempt to find the inserted node and move the caret appropriately
if (newRoot != null)
......@@ -74,7 +76,7 @@ public void Commit(CompletionItem completionItem, ITextView textView, ITextBuffe
});
}
private Document DetermineNewDocument(MemberInsertionCompletionItem completionItem, ITextSnapshot textSnapshot, CancellationToken cancellationToken)
private async Task<Document> DetermineNewDocumentAsync(MemberInsertionCompletionItem completionItem, ITextSnapshot textSnapshot, CancellationToken cancellationToken)
{
// The span we're going to replace
var line = textSnapshot.GetLineFromLineNumber(completionItem.Line);
......@@ -89,7 +91,7 @@ private Document DetermineNewDocument(MemberInsertionCompletionItem completionIt
var annotatedRoot = tree.GetRoot(cancellationToken).ReplaceToken(token, token.WithAdditionalAnnotations(_otherAnnotation));
document = document.WithSyntaxRoot(annotatedRoot);
Document memberContainingDocument = GenerateMemberAndUsings(document, completionItem, line, cancellationToken);
var memberContainingDocument = await GenerateMemberAndUsingsAsync(document, completionItem, line, cancellationToken).ConfigureAwait(false);
var insertionRoot = PrepareTreeForMemberInsertion(memberContainingDocument, cancellationToken);
var insertionText = GenerateInsertionText(memberContainingDocument, cancellationToken);
......@@ -106,7 +108,7 @@ private Document DetermineNewDocument(MemberInsertionCompletionItem completionIt
return Formatter.FormatAsync(document, _annotation, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
}
private Document GenerateMemberAndUsings(
private async Task<Document> GenerateMemberAndUsingsAsync(
Document document,
MemberInsertionCompletionItem completionItem,
ITextSnapshotLine line,
......@@ -124,7 +126,7 @@ private Document DetermineNewDocument(MemberInsertionCompletionItem completionIt
// CodeGenerationOptions containing before and after
var options = new CodeGenerationOptions(contextLocation: semanticModel.SyntaxTree.GetLocation(TextSpan.FromBounds(line.Start, line.Start)));
var generatedMember = GenerateMember(overriddenMember, containingType, document, completionItem, cancellationToken);
var generatedMember = await GenerateMemberAsync(overriddenMember, containingType, document, completionItem, cancellationToken).ConfigureAwait(false);
generatedMember = _annotation.AddAnnotationToSymbol(generatedMember);
Document memberContainingDocument = null;
......
......@@ -41,7 +41,7 @@ public override async Task ProduceCompletionListAsync(CompletionListContext cont
}
}
protected override ISymbol GenerateMember(ISymbol newOverriddenMember, INamedTypeSymbol newContainingType, Document newDocument, MemberInsertionCompletionItem completionItem, CancellationToken cancellationToken)
protected override async Task<ISymbol> GenerateMemberAsync(ISymbol newOverriddenMember, INamedTypeSymbol newContainingType, Document newDocument, MemberInsertionCompletionItem completionItem, CancellationToken cancellationToken)
{
// Figure out what to insert, and do it. Throw if we've somehow managed to get this far and can't.
var syntaxFactory = newDocument.GetLanguageService<SyntaxGenerator>();
......@@ -50,13 +50,13 @@ protected override ISymbol GenerateMember(ISymbol newOverriddenMember, INamedTyp
var modifiers = completionItem.Modifiers.WithIsUnsafe(completionItem.Modifiers.IsUnsafe | newOverriddenMember.IsUnsafe());
if (newOverriddenMember.Kind == SymbolKind.Method)
{
return syntaxFactory.OverrideMethod((IMethodSymbol)newOverriddenMember,
modifiers, newContainingType, newDocument, cancellationToken);
return await syntaxFactory.OverrideMethodAsync((IMethodSymbol)newOverriddenMember,
modifiers, newContainingType, newDocument, cancellationToken).ConfigureAwait(false);
}
else if (newOverriddenMember.Kind == SymbolKind.Property)
{
return syntaxFactory.OverrideProperty((IPropertySymbol)newOverriddenMember,
modifiers, newContainingType, newDocument, cancellationToken);
return await syntaxFactory.OverridePropertyAsync((IPropertySymbol)newOverriddenMember,
modifiers, newContainingType, newDocument, cancellationToken).ConfigureAwait(false);
}
else
{
......
......@@ -63,10 +63,10 @@ public override async Task ProduceCompletionListAsync(CompletionListContext cont
}
}
protected override ISymbol GenerateMember(ISymbol member, INamedTypeSymbol containingType, Document document, MemberInsertionCompletionItem item, CancellationToken cancellationToken)
protected override async Task<ISymbol> GenerateMemberAsync(ISymbol member, INamedTypeSymbol containingType, Document document, MemberInsertionCompletionItem item, CancellationToken cancellationToken)
{
var syntaxFactory = document.GetLanguageService<SyntaxGenerator>();
var semanticModel = document.GetSemanticModelAsync(cancellationToken).WaitAndGetResult(cancellationToken);
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
return CodeGenerationSymbolFactory.CreateMethodSymbol(attributes: new List<AttributeData>(),
accessibility: Accessibility.NotApplicable,
......
......@@ -14,8 +14,5 @@ ShellOutVital(Path.Combine(directoryUtil.RoslynDirectory, "Restore.cmd"), "", wo
// Build Roslyn in Release Mode
ShellOutVital("msbuild", "./Roslyn.sln /p:Configuration=Release", workingDirectory: directoryUtil.RoslynDirectory);
// Run DownloadTools before using the TraceManager because TraceManager uses the downloaded CPC binaries
DownloadTools();
// Run run_and_report.csx
await RunFile(Path.Combine(directoryUtil.MyWorkingDirectory, "run_and_report.csx"));
......@@ -9,7 +9,7 @@ using System.IO;
using System;
var directoryInfo = new RelativeDirectory();
var testDirectory = Path.Combine(directoryInfo.MyWorkingDirectory, "Tests");
var testDirectory = Path.Combine(directoryInfo.MyWorkingDirectory, "tests");
// Print message at startup
Log("Starting Performance Test Run");
......@@ -29,45 +29,31 @@ foreach (var script in GetAllCsxRecursive(testDirectory))
}
var traceManager = TraceManagerFactory.GetTraceManager();
traceManager.Setup();
for (int i = 0; i < traceManager.Iterations; i++)
{
traceManager.Start();
foreach (dynamic test in testInstances)
{
test.Setup();
traceManager.StartScenario(test.Name, test.MeasuredProc);
traceManager.StartEvent();
test.Test();
traceManager.EndEvent();
traceManager.EndScenario();
}
traceManager.EndScenarios();
traceManager.WriteScenariosFileToDisk();
traceManager.Stop();
traceManager.ResetScenarioGenerator();
}
traceManager.Cleanup();
/*
var traceManager = TraceManagerFactory.GetTraceManager();
traceManager.Setup();
// Run each of the tests
foreach (dynamic test in testInstances)
traceManager.Initialize();
foreach (dynamic test in testInstances)
{
test.Setup();
traceManager.Start();
for (int i = 0; i < test.Iterations; i++)
traceManager.Setup();
var iterations = traceManager.HasWarmUpIteration ?
test.Iterations + 1 :
test.Iterations;
for (int i = 0; i < iterations; i++)
{
traceManager.StartScenario("temp" + i, "csc");
traceManager.StartScenarios();
traceManager.Start();
traceManager.StartScenario(test.Name + i, test.MeasuredProc);
traceManager.StartEvent();
test.Test();
traceManager.EndEvent();
traceManager.EndScenario();
traceManager.EndScenarios();
traceManager.WriteScenariosFileToDisk();
traceManager.Stop();
traceManager.ResetScenarioGenerator();
}
traceManager.EndScenarios();
traceManager.WriteScenariosFileToDisk();
traceManager.Stop();
traceManager.Cleanup();
}
*/
......@@ -27,9 +27,9 @@ class CSharpCompilerTest: PerfTest
ShellOutVital(ReleaseCscPath, args, executeInDirectory);
}
public override int Iterations => 1;
public override int Iterations => 2;
public override string Name => "csharp " + _rspFile;
public override string MeasuredProc => "csc.exe";
public override string MeasuredProc => "csc";
}
TestThisPlease(
......
......@@ -21,9 +21,9 @@ class HelloWorldTest: PerfTest
ShellOutVital(ReleaseCscPath, _pathToHelloWorld + " /out:" + _pathToOutput);
}
public override int Iterations => 1;
public override int Iterations => 2;
public override string Name => "hello world";
public override string MeasuredProc => "csc.exe";
public override string MeasuredProc => "csc";
}
TestThisPlease(new HelloWorldTest());
......@@ -26,7 +26,6 @@ public class ScenarioGenerator
}
_buffer = new List<string>();
AddScenariosFileStart();
}
public void AddScenariosFileStart()
......
......@@ -31,6 +31,7 @@ bool ConvertConsumptionToCsv(string source, string destination, string requiredM
if (xmlReader.Name.Equals("ScenarioResult"))
{
currentScenarioName = xmlReader.GetAttribute("Name");
currentScenarioName = new string(currentScenarioName.TakeWhile(c => !Char.IsDigit(c)).ToArray());
// These are not test results
if (string.Equals(currentScenarioName, "..TestDiagnostics.."))
......@@ -132,16 +133,26 @@ void UploadTraces(string sourceFolderPath, string destinationFolderPath)
Log("Uploading traces");
if (Directory.Exists(sourceFolderPath))
{
// Get the latest written databackup
var directoryToUpload = new DirectoryInfo(sourceFolderPath).GetDirectories("DataBackup*").OrderByDescending(d=>d.LastWriteTimeUtc).FirstOrDefault();
if (directoryToUpload == null)
var directoriesToUpload = new DirectoryInfo(sourceFolderPath).GetDirectories("DataBackup*");
if (directoriesToUpload.Count() == 0)
{
Log($"There are no trace directory starting with DataBackup in {sourceFolderPath}");
return;
}
var destination = Path.Combine(destinationFolderPath, directoryToUpload.Name);
CopyDirectory(directoryToUpload.FullName, destination);
var perfResultDestinationFolderName = string.Format("PerfResults-{0:yyyy-MM-dd_hh-mm-ss-tt}", DateTime.Now);
var destination = Path.Combine(destinationFolderPath, perfResultDestinationFolderName);
foreach (var directoryToUpload in directoriesToUpload)
{
var destinationDataBackupDirectory = Path.Combine(destination, directoryToUpload.Name);
if (Directory.Exists(destinationDataBackupDirectory))
{
Directory.CreateDirectory(destinationDataBackupDirectory);
}
CopyDirectory(directoryToUpload.FullName, destinationDataBackupDirectory);
}
foreach(var file in new DirectoryInfo(sourceFolderPath).GetFiles().Where(f => f.Name.StartsWith("ConsumptionTemp", StringComparison.OrdinalIgnoreCase) || f.Name.StartsWith("Roslyn-", StringComparison.OrdinalIgnoreCase)))
{
......
......@@ -7,8 +7,9 @@ using System.IO;
interface ITraceManager
{
int Iterations { get; }
bool HasWarmUpIteration { get; }
void Initialize();
void Cleanup();
void EndEvent();
void EndScenario();
......@@ -18,24 +19,25 @@ interface ITraceManager
void Start();
void StartEvent();
void StartScenario(string scenarioName, string processName);
void StartScenarios();
void Stop();
void WriteScenariosFileToDisk();
}
class TraceManagerFactory
{
public static ITraceManager GetTraceManager(int iterations = 1)
public static ITraceManager GetTraceManager()
{
var directoryInfo = new RelativeDirectory();
var cpcFullPath = Path.Combine(directoryInfo.CPCDirectoryPath, "CPC.exe");
var scenarioPath = directoryInfo.CPCDirectoryPath;
if (File.Exists(cpcFullPath))
{
return new TraceManager(iterations, cpcFullPath, scenarioPath);
return new TraceManager(cpcFullPath, scenarioPath);
}
else
{
return new NoOpTraceManager(iterations);
return new NoOpTraceManager();
}
}
}
......@@ -44,18 +46,20 @@ class TraceManagerFactory
/// All operations are NoOp
class NoOpTraceManager : ITraceManager
{
private readonly int _iterations;
public NoOpTraceManager(int iterations)
public NoOpTraceManager()
{
_iterations = iterations;
}
public int Iterations
public bool HasWarmUpIteration
{
get
{
return _iterations;
}
return false;
}
}
public void Initialize()
{
}
public void Cleanup()
......@@ -90,6 +94,10 @@ class NoOpTraceManager : ITraceManager
{
}
public void StartScenarios()
{
}
public void StartScenario(string scenarioName, string processName)
{
}
......@@ -106,7 +114,6 @@ class NoOpTraceManager : ITraceManager
class TraceManager: ITraceManager
{
private readonly ScenarioGenerator _scenarioGenerator;
private readonly int _iterations;
private readonly string _cpcPath;
private RelativeDirectory _directoryInfo = new RelativeDirectory();
......@@ -115,20 +122,37 @@ class TraceManager: ITraceManager
private int _stopEventAbsoluteInstance = 1;
public TraceManager(
int iterations,
string cpcPath,
string scenarioPath): base()
{
_iterations = iterations;
_cpcPath = cpcPath;
_scenarioGenerator = new ScenarioGenerator(scenarioPath);
}
public int Iterations
public bool HasWarmUpIteration
{
get
{
return _iterations;
return true;
}
}
// Cleanup the results directory and files before every run
public void Initialize()
{
var consumptionTempResultsPath = Path.Combine(_directoryInfo.CPCDirectoryPath, "ConsumptionTempResults.xml");
if (File.Exists(consumptionTempResultsPath))
{
File.Delete(consumptionTempResultsPath);
}
if (Directory.Exists(_directoryInfo.CPCDirectoryPath))
{
var databackDirectories = Directory.GetDirectories(_directoryInfo.CPCDirectoryPath, "DataBackup*", SearchOption.AllDirectories);
foreach (var databackDirectory in databackDirectories)
{
Directory.Delete(databackDirectory, true);
}
}
}
......@@ -145,7 +169,7 @@ class TraceManager: ITraceManager
public void Stop()
{
var scenariosXmlPath = Path.Combine(_directoryInfo.CPCDirectoryPath, "scenarios.xml");
var consumptionTempResultsPath = Path.Combine(_directoryInfo.CPCDirectoryPath, "ConsumptionTempResultsPath.xml");
var consumptionTempResultsPath = Path.Combine(_directoryInfo.CPCDirectoryPath, "ConsumptionTempResults.xml");
ShellOutVital(_cpcPath, $"/Stop /DisableArchive /ScenarioPath=\"{scenariosXmlPath}\" /ConsumptionTempResultsPath=\"{consumptionTempResultsPath}\"");
}
......@@ -153,6 +177,11 @@ class TraceManager: ITraceManager
{
ShellOutVital(_cpcPath, "/Cleanup /DisableArchive");
}
public void StartScenarios()
{
_scenarioGenerator.AddScenariosFileStart();
}
public void StartScenario(string scenarioName, string processName)
{
......
......@@ -45,11 +45,6 @@ public class CompilationVerifier
_dependencies = dependencies;
}
public CompilationVerifier Clone()
{
return new CompilationVerifier(_test, _compilation, _dependencies);
}
internal CompilationTestData TestData
{
get { return _testData; }
......@@ -94,7 +89,7 @@ internal ImmutableArray<ModuleMetadata> GetAllModuleMetadata()
public void Emit(string expectedOutput, IEnumerable<ResourceDescription> manifestResources, bool peVerify, SignatureDescription[] expectedSignatures)
{
using (var testEnvironment = new HostedRuntimeEnvironment(_dependencies))
using (var testEnvironment = RuntimeEnvironmentFactory.Create(_dependencies))
{
string mainModuleName = Emit(testEnvironment, manifestResources);
_allModuleData = testEnvironment.GetAllModuleData();
......@@ -120,7 +115,7 @@ public void Emit(string expectedOutput, IEnumerable<ResourceDescription> manifes
// Replace bool verify parameter with string[] expectedPeVerifyOutput. If null, no verification. If empty verify have to succeed. Otherwise compare errors.
public void EmitAndVerify(params string[] expectedPeVerifyOutput)
{
using (var testEnvironment = new HostedRuntimeEnvironment(_dependencies))
using (var testEnvironment = RuntimeEnvironmentFactory.Create(_dependencies))
{
string mainModuleName = Emit(testEnvironment, null);
string[] actualOutput = testEnvironment.PeVerifyModules(new[] { mainModuleName }, throwOnError: false);
......@@ -128,14 +123,14 @@ public void EmitAndVerify(params string[] expectedPeVerifyOutput)
}
}
private string Emit(HostedRuntimeEnvironment testEnvironment, IEnumerable<ResourceDescription> manifestResources)
private string Emit(IRuntimeEnvironment testEnvironment, IEnumerable<ResourceDescription> manifestResources)
{
testEnvironment.Emit(_compilation, manifestResources);
_diagnostics = testEnvironment.GetDiagnostics();
EmittedAssemblyData = testEnvironment.GetMainImage();
EmittedAssemblyPdb = testEnvironment.GetMainPdb();
_testData = testEnvironment.GetCompilationTestData();
_testData = ((IInternalRuntimeEnvironment) testEnvironment).GetCompilationTestData();
return _compilation.Assembly.Identity.GetDisplayName();
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Emit;
using Roslyn.Utilities;
using static Roslyn.Test.Utilities.ExceptionHelper;
namespace Microsoft.CodeAnalysis.Test.Utilities
{
......@@ -23,84 +12,35 @@ public class EmitException : Exception
{
public IEnumerable<Diagnostic> Diagnostics { get; }
protected EmitException(SerializationInfo info, StreamingContext context) : base(info, context) { }
protected EmitException(SerializationInfo info, StreamingContext context)
: base(info, context) { }
public EmitException(IEnumerable<Diagnostic> diagnostics, string directory)
: base(GetMessageFromResult(diagnostics, directory))
{
this.Diagnostics = diagnostics;
}
private static string GetMessageFromResult(IEnumerable<Diagnostic> diagnostics, string directory)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("Emit Failed, binaries saved to: ");
sb.AppendLine(directory);
foreach (var d in diagnostics)
{
sb.AppendLine(d.ToString());
}
return sb.ToString();
}
}
[Serializable]
public class PeVerifyException : Exception
{
protected PeVerifyException(SerializationInfo info, StreamingContext context) : base(info, context) { }
protected PeVerifyException(SerializationInfo info, StreamingContext context)
: base(info, context) { }
public PeVerifyException(string output, string exePath) : base(GetMessageFromResult(output, exePath)) { }
public PeVerifyException(string output, string exePath)
: base(GetMessageFromResult(output, exePath)) { }
private static string GetMessageFromResult(string output, string exePath)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine();
sb.Append("PeVerify failed for assembly '");
sb.Append(exePath);
sb.AppendLine("':");
sb.AppendLine(output);
return sb.ToString();
}
}
[Serializable]
public class ExecutionException : Exception
{
public ExecutionException(string expectedOutput, string actualOutput, string exePath) : base(GetMessageFromResult(expectedOutput, actualOutput, exePath)) { }
public ExecutionException(string expectedOutput, string actualOutput, string exePath)
: base(GetMessageFromResult(expectedOutput, actualOutput, exePath)) { }
public ExecutionException(Exception innerException, string exePath) : base(GetMessageFromException(innerException, exePath), innerException) { }
public ExecutionException(Exception innerException, string exePath)
: base(GetMessageFromException(innerException, exePath), innerException) { }
private static string GetMessageFromException(Exception executionException, string exePath)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine();
sb.Append("Execution failed for assembly '");
sb.Append(exePath);
sb.AppendLine("'.");
sb.Append("Exception: " + executionException);
return sb.ToString();
}
private static string GetMessageFromResult(string expectedOutput, string actualOutput, string exePath)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine();
sb.Append("Execution failed for assembly '");
sb.Append(exePath);
sb.AppendLine("'.");
if (expectedOutput != null)
{
sb.Append("Expected: ");
sb.AppendLine(expectedOutput);
sb.Append("Actual: ");
sb.AppendLine(actualOutput);
}
else
{
sb.Append("Output: ");
sb.AppendLine(actualOutput);
}
return sb.ToString();
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Emit;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using static Roslyn.Test.Utilities.RuntimeUtilities;
namespace Microsoft.CodeAnalysis.Test.Utilities
{
public sealed class HostedRuntimeEnvironment : IDisposable
public sealed class HostedRuntimeEnvironment : IDisposable, IRuntimeEnvironment, IInternalRuntimeEnvironment
{
private sealed class RuntimeData : IDisposable
{
......@@ -55,18 +53,6 @@ public void Dispose()
}
}
private struct EmitOutput
{
internal ImmutableArray<byte> Assembly { get; }
internal ImmutableArray<byte> Pdb { get; }
internal EmitOutput(ImmutableArray<byte> assembly, ImmutableArray<byte> pdb)
{
Assembly = assembly;
Pdb = pdb;
}
}
private sealed class EmitData
{
internal RuntimeData RuntimeData;
......@@ -200,200 +186,6 @@ private static RuntimeData CreateRuntimeData()
}
}
/// <summary>
/// Find all of the <see cref="Compilation"/> values reachable from this instance.
/// </summary>
/// <param name="compilation"></param>
/// <returns></returns>
private static List<Compilation> FindReferencedCompilations(Compilation original)
{
var list = new List<Compilation>();
var toVisit = new Queue<Compilation>(FindDirectReferencedCompilations(original));
while (toVisit.Count > 0)
{
var current = toVisit.Dequeue();
if (list.Contains(current))
{
continue;
}
list.Add(current);
foreach (var other in FindDirectReferencedCompilations(current))
{
toVisit.Enqueue(other);
}
}
return list;
}
private static List<Compilation> FindDirectReferencedCompilations(Compilation compilation)
{
var list = new List<Compilation>();
var previousCompilation = compilation.ScriptCompilationInfo?.PreviousScriptCompilation;
if (previousCompilation != null)
{
list.Add(previousCompilation);
}
foreach (var reference in compilation.References.OfType<CompilationReference>())
{
list.Add(reference.Compilation);
}
return list;
}
/// <summary>
/// Emit all of the references which are not directly or indirectly a <see cref="Compilation"/> value.
/// </summary>
private static void EmitReferences(Compilation compilation, HashSet<string> fullNameSet, List<ModuleData> dependencies, DiagnosticBag diagnostics)
{
// NOTE: specifically don't need to consider previous submissions since they will always be compilations.
foreach (var metadataReference in compilation.References)
{
if (metadataReference is CompilationReference)
{
continue;
}
var peRef = (PortableExecutableReference)metadataReference;
var metadata = peRef.GetMetadata();
var isManifestModule = peRef.Properties.Kind == MetadataImageKind.Assembly;
var identity = isManifestModule
? ((AssemblyMetadata)metadata).GetAssembly().Identity
: null;
// If this is an indirect reference to a Compilation then it is already been emitted
// so no more work to be done.
if (isManifestModule && fullNameSet.Contains(identity.GetDisplayName()))
{
continue;
}
foreach (var module in EnumerateModules(metadata))
{
ImmutableArray<byte> bytes = module.Module.PEReaderOpt.GetEntireImage().GetContent();
ModuleData moduleData;
if (isManifestModule)
{
fullNameSet.Add(identity.GetDisplayName());
moduleData = new ModuleData(identity,
OutputKind.DynamicallyLinkedLibrary,
bytes,
pdb: default(ImmutableArray<byte>),
inMemoryModule: true);
}
else
{
moduleData = new ModuleData(module.Name,
bytes,
pdb: default(ImmutableArray<byte>),
inMemoryModule: true);
}
dependencies.Add(moduleData);
isManifestModule = false;
}
}
}
private static IEnumerable<ModuleMetadata> EnumerateModules(Metadata metadata)
{
return (metadata.Kind == MetadataImageKind.Assembly) ? ((AssemblyMetadata)metadata).GetModules().AsEnumerable() : SpecializedCollections.SingletonEnumerable((ModuleMetadata)metadata);
}
private static EmitOutput? EmitCompilation(
Compilation compilation,
IEnumerable<ResourceDescription> manifestResources,
List<ModuleData> dependencies,
DiagnosticBag diagnostics,
CompilationTestData testData
)
{
// A Compilation can appear multiple times in a depnedency graph as both a Compilation and as a MetadataReference
// value. Iterate the Compilations eagerly so they are always emitted directly and later references can re-use
// the value. This gives better, and consistent, diagostic information.
var referencedCompilations = FindReferencedCompilations(compilation);
var fullNameSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var referencedCompilation in referencedCompilations)
{
var emitData = EmitCompilationCore(referencedCompilation, null, diagnostics, null);
if (emitData.HasValue)
{
var moduleData = new ModuleData(referencedCompilation.Assembly.Identity,
OutputKind.DynamicallyLinkedLibrary,
emitData.Value.Assembly,
pdb: default(ImmutableArray<byte>),
inMemoryModule: true);
fullNameSet.Add(moduleData.Id.FullName);
dependencies.Add(moduleData);
}
}
// Now that the Compilation values have been emitted, emit the non-compilation references
foreach (var current in (new[] { compilation }).Concat(referencedCompilations))
{
EmitReferences(current, fullNameSet, dependencies, diagnostics);
}
return EmitCompilationCore(compilation, manifestResources, diagnostics, testData);
}
private static EmitOutput? EmitCompilationCore(
Compilation compilation,
IEnumerable<ResourceDescription> manifestResources,
DiagnosticBag diagnostics,
CompilationTestData testData
)
{
using (var executableStream = new MemoryStream())
{
var pdb = default(ImmutableArray<byte>);
var assembly = default(ImmutableArray<byte>);
var pdbStream = MonoHelpers.IsRunningOnMono()
? null
: new MemoryStream();
EmitResult result;
try
{
result = compilation.Emit(
executableStream,
pdbStream: pdbStream,
xmlDocumentationStream: null,
win32Resources: null,
manifestResources: manifestResources,
options: EmitOptions.Default,
debugEntryPoint: null,
testData: testData,
getHostDiagnostics: null,
cancellationToken: default(CancellationToken));
}
finally
{
if (pdbStream != null)
{
pdb = pdbStream.ToImmutable();
pdbStream.Dispose();
}
}
diagnostics.AddRange(result.Diagnostics);
assembly = executableStream.ToImmutable();
if (result.Success)
{
return new EmitOutput(assembly, pdb);
}
return null;
}
}
public void Emit(
Compilation mainCompilation,
IEnumerable<ResourceDescription> manifestResources,
......@@ -430,7 +222,7 @@ CompilationTestData testData
else
{
string dumpDir;
RuntimeAssemblyManager.DumpAssemblyData(dependencies, out dumpDir);
DumpAssemblyData(dependencies, out dumpDir);
// This method MUST throw if compilation did not succeed. If compilation succeeded and there were errors, that is bad.
// Please see KevinH if you intend to change this behavior as many tests expect the Exception to indicate failure.
......@@ -484,7 +276,7 @@ private EmitData GetEmitData()
return _emitData;
}
internal ImmutableArray<Diagnostic> GetDiagnostics()
public ImmutableArray<Diagnostic> GetDiagnostics()
{
return GetEmitData().Diagnostics;
}
......@@ -499,7 +291,7 @@ public ImmutableArray<byte> GetMainPdb()
return GetEmitData().MainModulePdb;
}
internal IList<ModuleData> GetAllModuleData()
public IList<ModuleData> GetAllModuleData()
{
return GetEmitData().AllModuleData;
}
......@@ -511,14 +303,14 @@ public void PeVerify()
emitData.Manager.PeVerifyModules(new[] { emitData.MainModule.FullName });
}
internal string[] PeVerifyModules(string[] modulesToVerify, bool throwOnError = true)
public string[] PeVerifyModules(string[] modulesToVerify, bool throwOnError = true)
{
var emitData = GetEmitData();
emitData.RuntimeData.PeverifyRequested = true;
return emitData.Manager.PeVerifyModules(modulesToVerify, throwOnError);
}
internal SortedSet<string> GetMemberSignaturesFromMetadata(string fullyQualifiedTypeName, string memberName)
public SortedSet<string> GetMemberSignaturesFromMetadata(string fullyQualifiedTypeName, string memberName)
{
var emitData = GetEmitData();
var searchIds = emitData.AllModuleData.Select(x => x.Id).ToList();
......@@ -554,7 +346,7 @@ void IDisposable.Dispose()
_disposed = true;
}
internal CompilationTestData GetCompilationTestData()
CompilationTestData IInternalRuntimeEnvironment.GetCompilationTestData()
{
if (_testData.Module == null)
{
......
......@@ -15,15 +15,15 @@ public class SignatureDescription
public string ExpectedSignature { get; set; }
}
public class MetadataSignatureUnitTestHelper
internal class MetadataSignatureUnitTestHelper
{
/// <summary>
/// Uses Reflection to verify that the specified member signatures are present in emitted metadata
/// </summary>
/// <param name="appDomainHost">Unit test AppDomain host</param>
/// <param name="expectedSignatures">Baseline signatures - use the Signature() factory method to create instances of SignatureDescription</param>
public static void VerifyMemberSignatures(
HostedRuntimeEnvironment appDomainHost, params SignatureDescription[] expectedSignatures)
internal static void VerifyMemberSignatures(
IRuntimeEnvironment appDomainHost, params SignatureDescription[] expectedSignatures)
{
Assert.NotNull(expectedSignatures);
Assert.NotEmpty(expectedSignatures);
......@@ -76,7 +76,7 @@ public class MetadataSignatureUnitTestHelper
/// <param name="actualSignatures">List of found signatures matching member name</param>
/// <returns>True if a matching member signature was found, false otherwise</returns>
private static bool VerifyMemberSignatureHelper(
HostedRuntimeEnvironment appDomainHost, string fullyQualifiedTypeName, string memberName,
IRuntimeEnvironment appDomainHost, string fullyQualifiedTypeName, string memberName,
ref string expectedSignature, out List<string> actualSignatures)
{
Assert.False(string.IsNullOrWhiteSpace(fullyQualifiedTypeName), "'fullyQualifiedTypeName' can't be null or empty");
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Emit;
using Roslyn.Utilities;
using Roslyn.Test.Utilities;
namespace Microsoft.CodeAnalysis.Test.Utilities
{
......@@ -46,8 +39,6 @@ internal AssemblyData(Assembly assembly)
}
}
private static int s_dumpCount;
private readonly AppDomainAssemblyCache _assemblyCache = AppDomainAssemblyCache.GetOrCreate();
private readonly Dictionary<string, AssemblyData> _fullNameToAssemblyDataMap;
private readonly Dictionary<Guid, AssemblyData> _mvidToAssemblyDataMap;
......@@ -90,6 +81,11 @@ public RuntimeAssemblyManager()
}
}
public string DumpAssemblyData(out string dumpDirectory)
{
return RuntimeUtilities.DumpAssemblyData(ModuleDatas, out dumpDirectory);
}
public void Dispose()
{
// clean up our handlers, so that they don't accumulate
......@@ -430,87 +426,6 @@ public int Execute(string moduleName, int expectedOutputLength, out string outpu
return result is int ? (int)result : 0;
}
public string DumpAssemblyData(out string dumpDirectory)
{
return DumpAssemblyData(ModuleDatas, out dumpDirectory);
}
public static string DumpAssemblyData(IEnumerable<ModuleData> modules, out string dumpDirectory)
{
dumpDirectory = null;
StringBuilder sb = new StringBuilder();
foreach (var module in modules)
{
// Limit the number of dumps to 10. After 10 we're likely in a bad state and are
// dumping lots of unnecessary data.
if (s_dumpCount > 10)
{
break;
}
if (module.InMemoryModule)
{
Interlocked.Increment(ref s_dumpCount);
if (dumpDirectory == null)
{
var assemblyLocation = typeof(HostedRuntimeEnvironment).Assembly.Location;
dumpDirectory = Path.Combine(
Path.GetDirectoryName(assemblyLocation),
"Dumps");
try
{
Directory.CreateDirectory(dumpDirectory);
}
catch
{
// Okay if directory already exists
}
}
string fileName;
if (module.Kind == OutputKind.NetModule)
{
fileName = module.FullName;
}
else
{
AssemblyIdentity identity;
AssemblyIdentity.TryParseDisplayName(module.FullName, out identity);
fileName = identity.Name;
}
string pePath = Path.Combine(dumpDirectory, fileName + module.Kind.GetDefaultExtension());
string pdbPath = (module.Pdb != null) ? pdbPath = Path.Combine(dumpDirectory, fileName + ".pdb") : null;
try
{
module.Image.WriteToFile(pePath);
if (pdbPath != null)
{
module.Pdb.WriteToFile(pdbPath);
}
}
catch (IOException)
{
pePath = "<unable to write file>";
if (pdbPath != null)
{
pdbPath = "<unable to write file>";
}
}
sb.Append("PE(" + module.Kind + "): ");
sb.AppendLine(pePath);
if (pdbPath != null)
{
sb.Append("PDB: ");
sb.AppendLine(pdbPath);
}
}
}
return sb.ToString();
}
public string[] PeVerifyModules(string[] modulesToVerify, bool throwOnError = true)
{
// For Windows RT (ARM) THE CLRHelper.Peverify appears to not work and will exclude this
......@@ -552,7 +467,7 @@ public string[] PeVerifyModules(string[] modulesToVerify, bool throwOnError = tr
if (throwOnError && errors.Length > 0)
{
string dumpDir;
DumpAssemblyData(ModuleDatas, out dumpDir);
RuntimeUtilities.DumpAssemblyData(ModuleDatas, out dumpDir);
throw new PeVerifyException(errors.ToString(), dumpDir);
}
return allOutput.ToArray();
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CodeGen;
using Roslyn.Test.Utilities;
using static Roslyn.Test.Utilities.RuntimeUtilities;
namespace Microsoft.CodeAnalysis.Test.Utilities
{
public class CoreCLRRuntimeEnvironment : IRuntimeEnvironment, IInternalRuntimeEnvironment
{
private IEnumerable<ModuleData> _additionalDependencies;
private CompilationTestData _testData = new CompilationTestData();
private ImmutableArray<byte> _mainImage;
private ImmutableArray<byte> _pdb;
private ImmutableArray<Diagnostic> _diagnostics;
public CoreCLRRuntimeEnvironment(IEnumerable<ModuleData> additionalDependencies = null)
{
_additionalDependencies = additionalDependencies;
}
public void Emit(Compilation mainCompilation, IEnumerable<ResourceDescription> manifestResources, bool usePdbForDebugging = false)
{
_testData.Methods.Clear();
var diagnostics = DiagnosticBag.GetInstance();
var dependencies = new List<ModuleData>();
var mainOutput = RuntimeUtilities.EmitCompilation(mainCompilation, manifestResources, dependencies, diagnostics, _testData);
if (mainOutput.HasValue)
{
_diagnostics = diagnostics.ToReadOnly();
_mainImage = mainOutput.Value.Assembly;
_pdb = mainOutput.Value.Pdb;
}
else
{
_mainImage = default(ImmutableArray<byte>);
_pdb = default(ImmutableArray<byte>);
_diagnostics = default(ImmutableArray<Diagnostic>);
string dumpDir;
DumpAssemblyData(dependencies, out dumpDir);
throw new EmitException(diagnostics.ToReadOnly(), dumpDir);
}
}
public int Execute(string moduleName, string expectedOutput)
{
throw new NotImplementedException();
}
public IList<ModuleData> GetAllModuleData()
{
throw new NotImplementedException();
}
public ImmutableArray<Diagnostic> GetDiagnostics() => _diagnostics;
public ImmutableArray<byte> GetMainImage() => _mainImage;
public ImmutableArray<byte> GetMainPdb() => _pdb;
public SortedSet<string> GetMemberSignaturesFromMetadata(string fullyQualifiedTypeName, string memberName)
{
throw new NotImplementedException();
}
public void PeVerify()
{
throw new NotImplementedException();
}
public string[] PeVerifyModules(string[] modulesToVerify, bool throwOnError = true)
{
throw new NotImplementedException();
}
CompilationTestData IInternalRuntimeEnvironment.GetCompilationTestData()
{
return _testData;
}
public void Dispose()
{
// We need Dispose to satisfy the IRuntimeEnvironment interface, but
// we don't really need it.
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using static Roslyn.Test.Utilities.ExceptionHelper;
namespace Microsoft.CodeAnalysis.Test.Utilities
{
public sealed class EmitException : Exception
{
public IEnumerable<Diagnostic> Diagnostics { get; }
internal EmitException(IEnumerable<Diagnostic> diagnostics, string directory)
: base(GetMessageFromResult(diagnostics, directory))
{
this.Diagnostics = diagnostics;
}
}
public sealed class PeVerifyException : Exception
{
internal PeVerifyException(string output, string exePath) : base(GetMessageFromResult(output, exePath)) { }
}
public sealed class ExecutionException : Exception
{
internal ExecutionException(string expectedOutput, string actualOutput, string exePath) : base(GetMessageFromResult(expectedOutput, actualOutput, exePath)) { }
internal ExecutionException(Exception innerException, string exePath) : base(GetMessageFromException(innerException, exePath), innerException) { }
}
}
......@@ -115,6 +115,8 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CommonTestBase.cs" />
<Compile Include="CoreCLRRuntimeEnvironment.cs" />
<Compile Include="Exceptions.cs" />
<Compile Include="ICompilationVerifier.cs" />
<Compile Include="MetadataSignatureUnitTestHelper.cs" />
<Compile Include="ModuleData.cs" />
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Utilities;
namespace Roslyn.Test.Utilities
{
public class RuntimeEnvironmentFactory
{
internal static IRuntimeEnvironment Create(IEnumerable<ModuleData> additionalDependencies = null)
{
#if DNX
return new CoreCLRRuntimeEnvironment(additionalDependencies);
#else
return new HostedRuntimeEnvironment(additionalDependencies);
#endif
}
}
internal struct EmitOutput
{
internal ImmutableArray<byte> Assembly { get; }
internal ImmutableArray<byte> Pdb { get; }
internal EmitOutput(ImmutableArray<byte> assembly, ImmutableArray<byte> pdb)
{
Assembly = assembly;
Pdb = pdb;
}
}
internal static class RuntimeUtilities
{
private static int s_dumpCount;
private static IEnumerable<ModuleMetadata> EnumerateModules(Metadata metadata)
{
return (metadata.Kind == MetadataImageKind.Assembly) ? ((AssemblyMetadata)metadata).GetModules().AsEnumerable() : SpecializedCollections.SingletonEnumerable((ModuleMetadata)metadata);
}
/// <summary>
/// Emit all of the references which are not directly or indirectly a <see cref="Compilation"/> value.
/// </summary>
internal static void EmitReferences(Compilation compilation, HashSet<string> fullNameSet, List<ModuleData> dependencies, DiagnosticBag diagnostics)
{
// NOTE: specifically don't need to consider previous submissions since they will always be compilations.
foreach (var metadataReference in compilation.References)
{
if (metadataReference is CompilationReference)
{
continue;
}
var peRef = (PortableExecutableReference)metadataReference;
var metadata = peRef.GetMetadata();
var isManifestModule = peRef.Properties.Kind == MetadataImageKind.Assembly;
var identity = isManifestModule
? ((AssemblyMetadata)metadata).GetAssembly().Identity
: null;
// If this is an indirect reference to a Compilation then it is already been emitted
// so no more work to be done.
if (isManifestModule && fullNameSet.Contains(identity.GetDisplayName()))
{
continue;
}
foreach (var module in EnumerateModules(metadata))
{
ImmutableArray<byte> bytes = module.Module.PEReaderOpt.GetEntireImage().GetContent();
ModuleData moduleData;
if (isManifestModule)
{
fullNameSet.Add(identity.GetDisplayName());
moduleData = new ModuleData(identity,
OutputKind.DynamicallyLinkedLibrary,
bytes,
pdb: default(ImmutableArray<byte>),
inMemoryModule: true);
}
else
{
moduleData = new ModuleData(module.Name,
bytes,
pdb: default(ImmutableArray<byte>),
inMemoryModule: true);
}
dependencies.Add(moduleData);
isManifestModule = false;
}
}
}
/// <summary>
/// Find all of the <see cref="Compilation"/> values reachable from this instance.
/// </summary>
/// <param name="compilation"></param>
/// <returns></returns>
private static List<Compilation> FindReferencedCompilations(Compilation original)
{
var list = new List<Compilation>();
var toVisit = new Queue<Compilation>(FindDirectReferencedCompilations(original));
while (toVisit.Count > 0)
{
var current = toVisit.Dequeue();
if (list.Contains(current))
{
continue;
}
list.Add(current);
foreach (var other in FindDirectReferencedCompilations(current))
{
toVisit.Enqueue(other);
}
}
return list;
}
private static List<Compilation> FindDirectReferencedCompilations(Compilation compilation)
{
var list = new List<Compilation>();
var previousCompilation = compilation.ScriptCompilationInfo?.PreviousScriptCompilation;
if (previousCompilation != null)
{
list.Add(previousCompilation);
}
foreach (var reference in compilation.References.OfType<CompilationReference>())
{
list.Add(reference.Compilation);
}
return list;
}
internal static EmitOutput? EmitCompilation(
Compilation compilation,
IEnumerable<ResourceDescription> manifestResources,
List<ModuleData> dependencies,
DiagnosticBag diagnostics,
CompilationTestData testData
)
{
// A Compilation can appear multiple times in a depnedency graph as both a Compilation and as a MetadataReference
// value. Iterate the Compilations eagerly so they are always emitted directly and later references can re-use
// the value. This gives better, and consistent, diagostic information.
var referencedCompilations = FindReferencedCompilations(compilation);
var fullNameSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var referencedCompilation in referencedCompilations)
{
var emitData = RuntimeUtilities.EmitCompilationCore(referencedCompilation, null, diagnostics, null);
if (emitData.HasValue)
{
var moduleData = new ModuleData(referencedCompilation.Assembly.Identity,
OutputKind.DynamicallyLinkedLibrary,
emitData.Value.Assembly,
pdb: default(ImmutableArray<byte>),
inMemoryModule: true);
fullNameSet.Add(moduleData.Id.FullName);
dependencies.Add(moduleData);
}
}
// Now that the Compilation values have been emitted, emit the non-compilation references
foreach (var current in (new[] { compilation }).Concat(referencedCompilations))
{
EmitReferences(current, fullNameSet, dependencies, diagnostics);
}
return RuntimeUtilities.EmitCompilationCore(compilation, manifestResources, diagnostics, testData);
}
internal static EmitOutput? EmitCompilationCore(
Compilation compilation,
IEnumerable<ResourceDescription> manifestResources,
DiagnosticBag diagnostics,
CompilationTestData testData
)
{
using (var executableStream = new MemoryStream())
{
var pdb = default(ImmutableArray<byte>);
var assembly = default(ImmutableArray<byte>);
var pdbStream = MonoHelpers.IsRunningOnMono()
? null
: new MemoryStream();
EmitResult result;
try
{
result = compilation.Emit(
executableStream,
pdbStream: pdbStream,
xmlDocumentationStream: null,
win32Resources: null,
manifestResources: manifestResources,
options: EmitOptions.Default,
debugEntryPoint: null,
testData: testData,
getHostDiagnostics: null,
cancellationToken: default(CancellationToken));
}
finally
{
if (pdbStream != null)
{
pdb = pdbStream.ToImmutable();
pdbStream.Dispose();
}
}
diagnostics.AddRange(result.Diagnostics);
assembly = executableStream.ToImmutable();
if (result.Success)
{
return new EmitOutput(assembly, pdb);
}
return null;
}
}
public static string DumpAssemblyData(IEnumerable<ModuleData> modules, out string dumpDirectory)
{
dumpDirectory = null;
StringBuilder sb = new StringBuilder();
foreach (var module in modules)
{
// Limit the number of dumps to 10. After 10 we're likely in a bad state and are
// dumping lots of unnecessary data.
if (s_dumpCount > 10)
{
break;
}
if (module.InMemoryModule)
{
Interlocked.Increment(ref s_dumpCount);
if (dumpDirectory == null)
{
dumpDirectory = Path.GetTempPath();
try
{
Directory.CreateDirectory(dumpDirectory);
}
catch
{
// Okay if directory already exists
}
}
string fileName;
if (module.Kind == OutputKind.NetModule)
{
fileName = module.FullName;
}
else
{
AssemblyIdentity identity;
AssemblyIdentity.TryParseDisplayName(module.FullName, out identity);
fileName = identity.Name;
}
string pePath = Path.Combine(dumpDirectory, fileName + module.Kind.GetDefaultExtension());
string pdbPath = (module.Pdb != null) ? pdbPath = Path.Combine(dumpDirectory, fileName + ".pdb") : null;
try
{
module.Image.WriteToFile(pePath);
if (pdbPath != null)
{
module.Pdb.WriteToFile(pdbPath);
}
}
catch (IOException)
{
pePath = "<unable to write file>";
if (pdbPath != null)
{
pdbPath = "<unable to write file>";
}
}
sb.Append("PE(" + module.Kind + "): ");
sb.AppendLine(pePath);
if (pdbPath != null)
{
sb.Append("PDB: ");
sb.AppendLine(pdbPath);
}
}
}
return sb.ToString();
}
}
public interface IRuntimeEnvironment : IDisposable
{
void Emit(Microsoft.CodeAnalysis.Compilation mainCompilation, IEnumerable<ResourceDescription> manifestResources, bool usePdbForDebugging = false);
int Execute(string moduleName, string expectedOutput);
ImmutableArray<byte> GetMainImage();
ImmutableArray<byte> GetMainPdb();
ImmutableArray<Diagnostic> GetDiagnostics();
SortedSet<string> GetMemberSignaturesFromMetadata(string fullyQualifiedTypeName, string memberName);
IList<ModuleData> GetAllModuleData();
void PeVerify();
string[] PeVerifyModules(string[] modulesToVerify, bool throwOnError = true);
}
internal interface IInternalRuntimeEnvironment
{
CompilationTestData GetCompilationTestData();
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.CodeAnalysis;
namespace Roslyn.Test.Utilities
{
internal static class ExceptionHelper
{
internal static string GetMessageFromResult(IEnumerable<Diagnostic> diagnostics, string directory)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("Emit Failed, binaries saved to: ");
sb.AppendLine(directory);
foreach (var d in diagnostics)
{
sb.AppendLine(d.ToString());
}
return sb.ToString();
}
internal static string GetMessageFromResult(string output, string exePath)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine();
sb.Append("PeVerify failed for assembly '");
sb.Append(exePath);
sb.AppendLine("':");
sb.AppendLine(output);
return sb.ToString();
}
internal static string GetMessageFromException(Exception executionException, string exePath)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine();
sb.Append("Execution failed for assembly '");
sb.Append(exePath);
sb.AppendLine("'.");
sb.Append("Exception: " + executionException);
return sb.ToString();
}
internal static string GetMessageFromResult(string expectedOutput, string actualOutput, string exePath)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine();
sb.Append("Execution failed for assembly '");
sb.Append(exePath);
sb.AppendLine("'.");
if (expectedOutput != null)
{
sb.Append("Expected: ");
sb.AppendLine(expectedOutput);
sb.Append("Actual: ");
sb.AppendLine(actualOutput);
}
else
{
sb.Append("Output: ");
sb.AppendLine(actualOutput);
}
return sb.ToString();
}
}
}
......@@ -25,6 +25,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Compilation\CompilationExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Compilation\CompilationOutputFiles.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Compilation\CompilationTestDataExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Compilation\IRuntimeEnvironment.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Compilation\SpeculativeSemanticModelTestsBase.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Compilation\TestOperationWalker.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Compilation\VersionTestHelpers.cs" />
......@@ -36,6 +37,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\TestDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\ThrowingDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\TrackingDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ExceptionHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)FX\ConsoleOutput.cs" />
<Compile Include="$(MSBuildThisFileDirectory)FX\CultureHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)FX\DirectoryHelper.cs" />
......
......@@ -4,6 +4,7 @@
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.FindSymbols;
......@@ -208,7 +209,7 @@ private static bool TryGetValue(IDictionary<string, ISymbol> dictionary, string
}
}
public static IPropertySymbol OverrideProperty(
public static async Task<IPropertySymbol> OverridePropertyAsync(
this SyntaxGenerator codeFactory,
IPropertySymbol overriddenProperty,
DeclarationModifiers modifiers,
......@@ -225,7 +226,8 @@ private static bool TryGetValue(IDictionary<string, ISymbol> dictionary, string
// Implement an abstract property by throwing not implemented in accessors.
if (overriddenProperty.IsAbstract)
{
getBody = codeFactory.CreateThrowNotImplementStatement(document.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken));
var compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
getBody = codeFactory.CreateThrowNotImplementStatement(compilation);
setBody = getBody;
}
else if (overriddenProperty.IsIndexer() && document.Project.Language == LanguageNames.CSharp)
......@@ -247,8 +249,8 @@ private static bool TryGetValue(IDictionary<string, ISymbol> dictionary, string
{
// Call accessors directly if C# overriding VB
if (document.Project.Language == LanguageNames.CSharp
&& SymbolFinder.FindSourceDefinitionAsync(overriddenProperty, document.Project.Solution, cancellationToken)
.WaitAndGetResult(CancellationToken.None).Language == LanguageNames.VisualBasic)
&& (await SymbolFinder.FindSourceDefinitionAsync(overriddenProperty, document.Project.Solution, cancellationToken).ConfigureAwait(false))
.Language == LanguageNames.VisualBasic)
{
var getName = overriddenProperty.GetMethod != null ? overriddenProperty.GetMethod.Name : null;
var setName = overriddenProperty.SetMethod != null ? overriddenProperty.SetMethod.Name : null;
......@@ -351,7 +353,7 @@ private static bool TryGetValue(IDictionary<string, ISymbol> dictionary, string
name: overriddenEvent.Name);
}
public static IMethodSymbol OverrideMethod(
public static async Task<IMethodSymbol> OverrideMethodAsync(
this SyntaxGenerator codeFactory,
IMethodSymbol overriddenMethod,
DeclarationModifiers modifiers,
......@@ -362,11 +364,12 @@ private static bool TryGetValue(IDictionary<string, ISymbol> dictionary, string
// Abstract: Throw not implemented
if (overriddenMethod.IsAbstract)
{
var compilation = await newDocument.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
return CodeGenerationSymbolFactory.CreateMethodSymbol(
overriddenMethod,
accessibility: overriddenMethod.ComputeResultantAccessibility(newContainingType),
modifiers: modifiers,
statements: new[] { codeFactory.CreateThrowNotImplementStatement(newDocument.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken)) });
statements: new[] { codeFactory.CreateThrowNotImplementStatement(compilation) });
}
else
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册