提交 a13001c8 编写于 作者: Š Šimon Koníček

Merge remote-tracking branch 'upstream/master' into fixInterpolatedVerbatimString

......@@ -529,34 +529,6 @@ private void InferTypeArgsFirstPhase(Binder binder, ref HashSet<DiagnosticInfo>
private void MakeExplicitParameterTypeInferences(Binder binder, BoundExpression argument, TypeSymbolWithAnnotations target, ExactOrBoundsKind kind, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
// If the argument is a TYPEORNAMESPACEERROR and the pSource is an
// error type, then we want to set it to the generic error type
// that has no name text. This is because of the following scenario:
//
// void M<T>(T t) { }
// void Goo()
// {
// UnknownType t;
// M(t);
// M(undefinedVariable);
// }
//
// In the first call to M, we'll have an EXPRLOCAL with an error type,
// which is correct - we want the parameter help to display that we've
// got an inferred type of UnknownType, which is an error type since
// its undefined.
//
// However, for the M in the second call, we DON'T want to display parameter
// help that gives undefinedVariable as the type parameter for T, because
// there is no parameter of that name, let alone that type. This appears
// as an EXPRTYPEORNAMESPACEERROR with an ErrorType. We create a new error sym
// without the type name.
// UNDONE: if (pExpr->isTYPEORNAMESPACEERROR() && pSource->IsErrorType())
// UNDONE:{
// UNDONE: pSource = GetTypeManager().GetErrorSym();
// UNDONE:}
// SPEC: * If Ei is an anonymous function, an explicit type parameter
// SPEC: inference is made from Ei to Ti.
......
......@@ -80,9 +80,16 @@ internal static bool DetermineIfNewLineOptionIsSet(string value, NewLineOption o
}
private static NewLineOption? ConvertToNewLineOption(string value)
=> s_newLineOptionsEditorConfigMap.TryGetValue(value, out var option)
? option
: (NewLineOption?)null;
{
if (s_newLineOptionsEditorConfigMap.TryGetValue(value, out var option)) {
return option;
}
if (s_legacyNewLineOptionsEditorConfigMap.TryGetValue(value, out var legacyOption))
{
return legacyOption;
}
return null;
}
private static string GetNewLineOptionEditorConfigString(OptionSet optionSet)
{
......
......@@ -40,6 +40,11 @@ public static partial class CSharpFormattingOptions
KeyValuePairUtil.Create("no_change", LabelPositionOptions.NoIndent),
KeyValuePairUtil.Create("one_less_than_current", LabelPositionOptions.OneLess),
});
private static readonly BidirectionalMap<string, NewLineOption> s_legacyNewLineOptionsEditorConfigMap =
new BidirectionalMap<string, NewLineOption>(new[]
{
KeyValuePairUtil.Create("object_collection_array_initalizers", NewLineOption.ObjectCollectionsArrayInitializers),
});
private static readonly BidirectionalMap<string, NewLineOption> s_newLineOptionsEditorConfigMap =
new BidirectionalMap<string, NewLineOption>(new[]
{
......@@ -52,7 +57,7 @@ public static partial class CSharpFormattingOptions
KeyValuePairUtil.Create("anonymous_methods", NewLineOption.AnonymousMethods),
KeyValuePairUtil.Create("control_blocks", NewLineOption.ControlBlocks),
KeyValuePairUtil.Create("anonymous_types", NewLineOption.AnonymousTypes),
KeyValuePairUtil.Create("object_collection_array_initalizers", NewLineOption.ObjectCollectionsArrayInitializers),
KeyValuePairUtil.Create("object_collection_array_initializers", NewLineOption.ObjectCollectionsArrayInitializers),
KeyValuePairUtil.Create("lambdas", NewLineOption.Lambdas),
KeyValuePairUtil.Create("local_functions", NewLineOption.LocalFunction),
});
......
......@@ -92,6 +92,7 @@ static void TestParseEditorConfigLabelPositioningFalse(string value)
InlineData("control_blocks", NewLineOption.ControlBlocks),
InlineData("anonymous_types", NewLineOption.AnonymousTypes),
InlineData("object_collection_array_initalizers", NewLineOption.ObjectCollectionsArrayInitializers),
InlineData("object_collection_array_initializers", NewLineOption.ObjectCollectionsArrayInitializers),
InlineData("lambdas", NewLineOption.Lambdas),
InlineData("local_functions", NewLineOption.LocalFunction)]
static void TestParseNewLineOptionTrue(string value, NewLineOption option)
......
......@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
......@@ -38,107 +39,66 @@ internal class ProjectBuildManager
// don't actually run the compiler
{ PropertyNames.SkipCompilerExecution, bool.TrueString },
{ PropertyNames.ContinueOnError, PropertyValues.ErrorAndContinue }
{ PropertyNames.ContinueOnError, PropertyValues.ErrorAndContinue },
// this ensures that the parent project's configuration and platform will be used for
// referenced projects. So, setting Configuration=Release will also cause any project
// references to also be built with Configuration=Release. This is necessary for getting
// a more-likely-to-be-correct output path from project references.
{ PropertyNames.ShouldUnsetParentConfigurationAndPlatform, bool.FalseString }
}.ToImmutableDictionary();
private MSB.Evaluation.ProjectCollection _projectCollection;
private MSBuildDiagnosticLogger _logger;
private bool _started;
private readonly ImmutableDictionary<string, string> _additionalGlobalProperties;
private MSB.Evaluation.ProjectCollection _batchBuildProjectCollection;
private MSBuildDiagnosticLogger _batchBuildLogger;
private bool _batchBuildStarted;
~ProjectBuildManager()
{
if (_started)
if (_batchBuildStarted)
{
new InvalidOperationException("ProjectBuilderManager.Stop() not called.");
}
}
private static MSB.Evaluation.Project FindProject(
string path,
IDictionary<string, string> globalProperties,
MSB.Evaluation.ProjectCollection projectCollection,
CancellationToken cancellationToken)
public ProjectBuildManager(ImmutableDictionary<string, string> additionalGlobalProperties)
{
var loadedProjects = projectCollection.GetLoadedProjects(path);
if (loadedProjects == null || loadedProjects.Count == 0)
{
return null;
}
// We need to walk through all of the projects that have been previously loaded from this path and
// find the one that has the given set of global properties, plus the default global properties that
// we load every project with.
globalProperties = globalProperties ?? ImmutableDictionary<string, string>.Empty;
var totalGlobalProperties = projectCollection.GlobalProperties.Count + globalProperties.Count;
foreach (var loadedProject in loadedProjects)
{
cancellationToken.ThrowIfCancellationRequested();
// If this project has a different number of global properties than we expect, it's not the
// one we're looking for.
if (loadedProject.GlobalProperties.Count != totalGlobalProperties)
{
continue;
}
// Since we loaded all of them, the projects in this collection should all have the default
// global properties (i.e. the ones in _projectCollection.GlobalProperties). So, we just need to
// check the extra global properties.
var found = true;
foreach (var (key, value) in globalProperties)
{
// MSBuild escapes the values of a project's global properties, so we must too.
var escapedValue = MSB.Evaluation.ProjectCollection.Escape(value);
if (!loadedProject.GlobalProperties.TryGetValue(key, out var actualValue) ||
!string.Equals(actualValue, escapedValue, StringComparison.Ordinal))
{
found = false;
break;
}
}
if (found)
{
return loadedProject;
}
}
// We couldn't find a project with this path and the set of global properties we expect.
return null;
_additionalGlobalProperties = additionalGlobalProperties ?? ImmutableDictionary<string, string>.Empty;
}
public async Task<(MSB.Evaluation.Project project, DiagnosticLog log)> LoadProjectAsync(
string path, IDictionary<string, string> globalProperties, CancellationToken cancellationToken)
private ImmutableDictionary<string, string> AllGlobalProperties
=> s_defaultGlobalProperties.AddRange(_additionalGlobalProperties);
private static async Task<(MSB.Evaluation.Project project, DiagnosticLog log)> LoadProjectAsync(
string path, MSB.Evaluation.ProjectCollection projectCollection, CancellationToken cancellationToken)
{
var log = new DiagnosticLog();
try
{
var projectCollection = _projectCollection ?? new MSB.Evaluation.ProjectCollection(s_defaultGlobalProperties);
var loadedProjects = projectCollection.GetLoadedProjects(path);
if (loadedProjects != null && loadedProjects.Count > 0)
{
Debug.Assert(loadedProjects.Count == 1);
var project = FindProject(path, globalProperties, projectCollection, cancellationToken);
return (loadedProjects.First(), log);
}
if (project == null)
using (var stream = FileUtilities.OpenAsyncRead(path))
using (var readStream = await SerializableBytes.CreateReadableStreamAsync(stream, cancellationToken).ConfigureAwait(false))
using (var xmlReader = XmlReader.Create(readStream, s_xmlReaderSettings))
{
using (var stream = FileUtilities.OpenAsyncRead(path))
using (var readStream = await SerializableBytes.CreateReadableStreamAsync(stream, cancellationToken).ConfigureAwait(false))
using (var xmlReader = XmlReader.Create(readStream, s_xmlReaderSettings))
{
var xml = MSB.Construction.ProjectRootElement.Create(xmlReader, projectCollection);
var xml = MSB.Construction.ProjectRootElement.Create(xmlReader, projectCollection);
// When constructing a project from an XmlReader, MSBuild cannot determine the project file path. Setting the
// path explicitly is necessary so that the reserved properties like $(MSBuildProjectDirectory) will work.
xml.FullPath = path;
// When constructing a project from an XmlReader, MSBuild cannot determine the project file path. Setting the
// path explicitly is necessary so that the reserved properties like $(MSBuildProjectDirectory) will work.
xml.FullPath = path;
project = new MSB.Evaluation.Project(xml, globalProperties, toolsVersion: null, projectCollection);
}
}
var project = new MSB.Evaluation.Project(xml, globalProperties: null, toolsVersion: null, projectCollection);
return (project, log);
return (project, log);
}
}
catch (Exception e)
{
......@@ -147,42 +107,70 @@ internal class ProjectBuildManager
}
}
public Task<(MSB.Evaluation.Project project, DiagnosticLog log)> LoadProjectAsync(
string path, CancellationToken cancellationToken)
{
if (_batchBuildStarted)
{
return LoadProjectAsync(path, _batchBuildProjectCollection, cancellationToken);
}
else
{
var projectCollection = new MSB.Evaluation.ProjectCollection(AllGlobalProperties);
try
{
return LoadProjectAsync(path, projectCollection, cancellationToken);
}
finally
{
// unload project so collection will release global strings
projectCollection.UnloadAllProjects();
}
}
}
public async Task<string> TryGetOutputFilePathAsync(
string path, IDictionary<string, string> globalProperties, CancellationToken cancellationToken)
string path, CancellationToken cancellationToken)
{
// This tries to get the project output path and retrieving the $(TargetPath) property.
Debug.Assert(_batchBuildStarted);
// This tries to get the project output path and retrieving the evaluated $(TargetPath) property.
var (project, _) = await LoadProjectAsync(path, globalProperties, cancellationToken).ConfigureAwait(false);
var (project, _) = await LoadProjectAsync(path, cancellationToken).ConfigureAwait(false);
return project?.GetPropertyValue(PropertyNames.TargetPath);
}
public void Start()
public bool BatchBuildStarted => _batchBuildStarted;
public void StartBatchBuild(IDictionary<string, string> globalProperties = null)
{
if (_started)
if (_batchBuildStarted)
{
throw new InvalidOperationException();
}
_projectCollection = new MSB.Evaluation.ProjectCollection(s_defaultGlobalProperties);
globalProperties = globalProperties ?? ImmutableDictionary<string, string>.Empty;
var allProperties = s_defaultGlobalProperties.AddRange(globalProperties);
_batchBuildProjectCollection = new MSB.Evaluation.ProjectCollection(allProperties);
_logger = new MSBuildDiagnosticLogger()
_batchBuildLogger = new MSBuildDiagnosticLogger()
{
Verbosity = MSB.Framework.LoggerVerbosity.Normal
};
var buildParameters = new MSB.Execution.BuildParameters(_projectCollection)
var buildParameters = new MSB.Execution.BuildParameters(_batchBuildProjectCollection)
{
Loggers = new MSB.Framework.ILogger[] { _logger }
Loggers = new MSB.Framework.ILogger[] { _batchBuildLogger }
};
MSB.Execution.BuildManager.DefaultBuildManager.BeginBuild(buildParameters);
_started = true;
_batchBuildStarted = true;
}
public void Stop()
public void EndBatchBuild()
{
if (!_started)
if (!_batchBuildStarted)
{
throw new InvalidOperationException();
}
......@@ -190,16 +178,16 @@ public void Stop()
MSB.Execution.BuildManager.DefaultBuildManager.EndBuild();
// unload project so collection will release global strings
_projectCollection.UnloadAllProjects();
_projectCollection = null;
_logger = null;
_started = false;
_batchBuildProjectCollection.UnloadAllProjects();
_batchBuildProjectCollection = null;
_batchBuildLogger = null;
_batchBuildStarted = false;
}
public Task<MSB.Execution.ProjectInstance> BuildProjectAsync(
MSB.Evaluation.Project project, DiagnosticLog log, CancellationToken cancellationToken)
{
Debug.Assert(_started);
Debug.Assert(_batchBuildStarted);
var targets = new[] { TargetNames.Compile, TargetNames.CoreCompile };
......@@ -223,7 +211,7 @@ public void Stop()
}
}
_logger.SetProjectAndLog(projectInstance.FullPath, log);
_batchBuildLogger.SetProjectAndLog(projectInstance.FullPath, log);
var buildRequestData = new MSB.Execution.BuildRequestData(projectInstance, targets);
......
......@@ -49,6 +49,7 @@ internal static class PropertyNames
public const string RemoveIntegerChecks = nameof(RemoveIntegerChecks);
public const string ResolvedCodeAnalysisRuleSet = nameof(ResolvedCodeAnalysisRuleSet);
public const string RootNamespace = nameof(RootNamespace);
public const string ShouldUnsetParentConfigurationAndPlatform = nameof(ShouldUnsetParentConfigurationAndPlatform);
public const string SignAssembly = nameof(SignAssembly);
public const string SkipCompilerExecution = nameof(SkipCompilerExecution);
public const string StartupObject = nameof(StartupObject);
......
......@@ -130,7 +130,7 @@ public async Task<ImmutableArray<ProjectInfo>> LoadAsync(CancellationToken cance
var results = ImmutableArray.CreateBuilder<ProjectInfo>();
var processedPaths = new HashSet<string>(PathUtilities.Comparer);
_buildManager.Start();
_buildManager.StartBatchBuild(_globalProperties);
try
{
foreach (var projectPath in _requestedProjectPaths)
......@@ -171,7 +171,7 @@ public async Task<ImmutableArray<ProjectInfo>> LoadAsync(CancellationToken cance
}
finally
{
_buildManager.Stop();
_buildManager.EndBatchBuild();
}
}
......@@ -186,7 +186,7 @@ private async Task<ImmutableArray<ProjectFileInfo>> LoadProjectFileInfosAsync(st
ProjectLoadOperation.Evaluate,
projectPath,
targetFramework: null,
() => loader.LoadProjectFileAsync(projectPath, _globalProperties, _buildManager, cancellationToken)
() => loader.LoadProjectFileAsync(projectPath, _buildManager, cancellationToken)
).ConfigureAwait(false);
// If there were any failures during load, we won't be able to build the project. So, bail early with an empty project.
......
......@@ -314,7 +314,7 @@ private bool IsProjectLoadable(string projectPath)
private async Task<bool> VerifyUnloadableProjectOutputExistsAsync(string projectPath, ResolvedReferencesBuilder builder, CancellationToken cancellationToken)
{
var outputFilePath = await _buildManager.TryGetOutputFilePathAsync(projectPath, _globalProperties, cancellationToken).ConfigureAwait(false);
var outputFilePath = await _buildManager.TryGetOutputFilePathAsync(projectPath, cancellationToken).ConfigureAwait(false);
return builder.Contains(outputFilePath)
&& File.Exists(outputFilePath);
}
......
......@@ -27,8 +27,6 @@ public partial class MSBuildProjectLoader
private readonly NonReentrantLock _dataGuard = new NonReentrantLock();
private ImmutableDictionary<string, string> _properties;
internal readonly ProjectBuildManager BuildManager;
internal MSBuildProjectLoader(
Workspace workspace,
DiagnosticReporter diagnosticReporter,
......@@ -46,8 +44,6 @@ public partial class MSBuildProjectLoader
{
_properties = _properties.AddRange(properties);
}
BuildManager = new ProjectBuildManager();
}
/// <summary>
......@@ -183,12 +179,14 @@ private DiagnosticReportingMode GetReportingModeForUnrecognizedProjects()
}
}
var buildManager = new ProjectBuildManager(_properties);
var worker = new Worker(
_workspace,
_diagnosticReporter,
_pathResolver,
_projectFileLoaderRegistry,
BuildManager,
buildManager,
projectPaths.ToImmutable(),
baseDirectory: Path.GetDirectoryName(absoluteSolutionPath),
_properties,
......@@ -237,12 +235,14 @@ private DiagnosticReportingMode GetReportingModeForUnrecognizedProjects()
onPathFailure: reportingMode,
onLoaderFailure: reportingMode);
var buildManager = new ProjectBuildManager(_properties);
var worker = new Worker(
_workspace,
_diagnosticReporter,
_pathResolver,
_projectFileLoaderRegistry,
BuildManager,
buildManager,
requestedProjectPaths: ImmutableArray.Create(projectFilePath),
baseDirectory: Directory.GetCurrentDirectory(),
globalProperties: _properties,
......
......@@ -13,6 +13,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.MSBuild.Build;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
......@@ -281,11 +282,12 @@ protected override void ApplyProjectChanges(ProjectChanges projectChanges)
if (this.HasProjectFileChanges(projectChanges))
{
var projectPath = project.FilePath;
if (_projectFileLoaderRegistry.TryGetLoaderFromProjectPath(projectPath, out var loader))
if (_projectFileLoaderRegistry.TryGetLoaderFromProjectPath(projectPath, out var fileLoader))
{
try
{
_applyChangesProjectFile = loader.LoadProjectFileAsync(projectPath, _loader.Properties, _loader.BuildManager, CancellationToken.None).Result;
var buildManager = new ProjectBuildManager(_loader.Properties);
_applyChangesProjectFile = fileLoader.LoadProjectFileAsync(projectPath, buildManager, CancellationToken.None).Result;
}
catch (IOException exception)
{
......
// 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.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
......@@ -13,7 +12,6 @@ internal interface IProjectFileLoader : ILanguageService
string Language { get; }
Task<IProjectFile> LoadProjectFileAsync(
string path,
IDictionary<string, string> globalProperties,
ProjectBuildManager buildManager,
CancellationToken cancellationToken);
}
......
// 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.Linq;
using System.Threading;
using System.Threading.Tasks;
......@@ -19,7 +18,7 @@ internal abstract class ProjectFileLoader : IProjectFileLoader
protected abstract ProjectFile CreateProjectFile(MSB.Evaluation.Project project, ProjectBuildManager buildManager, DiagnosticLog log);
public async Task<IProjectFile> LoadProjectFileAsync(string path, IDictionary<string, string> globalProperties, ProjectBuildManager buildManager, CancellationToken cancellationToken)
public async Task<IProjectFile> LoadProjectFileAsync(string path, ProjectBuildManager buildManager, CancellationToken cancellationToken)
{
if (path == null)
{
......@@ -27,7 +26,7 @@ public async Task<IProjectFile> LoadProjectFileAsync(string path, IDictionary<st
}
// load project file async
var (project, log) = await buildManager.LoadProjectAsync(path, globalProperties, cancellationToken).ConfigureAwait(false);
var (project, log) = await buildManager.LoadProjectAsync(path, cancellationToken).ConfigureAwait(false);
return this.CreateProjectFile(project, buildManager, log);
}
......
using System;
using System.Threading.Tasks;
using ReferencedLibrary;
namespace InspectedLibrary
{
[SomeMetadata]
public class InspectedClass
{
public Task DoAsync()
{
throw new NotImplementedException();
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\ReferencedLibrary\ReferencedLibrary.csproj" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
</Project>
using System;
namespace ReferencedLibrary
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class SomeMetadataAttribute : Attribute
{
}
}

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReferencedLibrary", "ReferencedLibrary\ReferencedLibrary.csproj", "{A5800480-7965-4BA3-95F5-4830B831163D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InspectedLibrary", "InspectedLibrary\InspectedLibrary.csproj", "{86B44D47-6E01-4385-AFDB-C82695AFD2DA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A5800480-7965-4BA3-95F5-4830B831163D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5800480-7965-4BA3-95F5-4830B831163D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5800480-7965-4BA3-95F5-4830B831163D}.Debug|x64.ActiveCfg = Debug|Any CPU
{A5800480-7965-4BA3-95F5-4830B831163D}.Debug|x64.Build.0 = Debug|Any CPU
{A5800480-7965-4BA3-95F5-4830B831163D}.Debug|x86.ActiveCfg = Debug|Any CPU
{A5800480-7965-4BA3-95F5-4830B831163D}.Debug|x86.Build.0 = Debug|Any CPU
{A5800480-7965-4BA3-95F5-4830B831163D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5800480-7965-4BA3-95F5-4830B831163D}.Release|Any CPU.Build.0 = Release|Any CPU
{A5800480-7965-4BA3-95F5-4830B831163D}.Release|x64.ActiveCfg = Release|Any CPU
{A5800480-7965-4BA3-95F5-4830B831163D}.Release|x64.Build.0 = Release|Any CPU
{A5800480-7965-4BA3-95F5-4830B831163D}.Release|x86.ActiveCfg = Release|Any CPU
{A5800480-7965-4BA3-95F5-4830B831163D}.Release|x86.Build.0 = Release|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Debug|x64.ActiveCfg = Debug|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Debug|x64.Build.0 = Debug|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Debug|x86.ActiveCfg = Debug|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Debug|x86.Build.0 = Debug|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Release|Any CPU.Build.0 = Release|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Release|x64.ActiveCfg = Release|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Release|x64.Build.0 = Release|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Release|x86.ActiveCfg = Release|Any CPU
{86B44D47-6E01-4385-AFDB-C82695AFD2DA}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
......@@ -87,6 +87,7 @@ public static class SolutionFiles
public static string DuplicatedGuidsBecomeCircularReferential => GetText("SolutionFiles.DuplicatedGuidsBecomeCircularReferential.sln");
public static string EmptyLineBetweenProjectBlock => GetText("SolutionFiles.EmptyLineBetweenProjectBlock.sln");
public static string Issue29122_Solution => GetText("Issue29122.TestVB2.sln");
public static string Issue30174_Solution => GetText("Issue30174.Solution.sln");
public static string InvalidProjectPath => GetText("SolutionFiles.InvalidProjectPath.sln");
public static string MissingEndProject1 => GetText("SolutionFiles.MissingEndProject1.sln");
public static string MissingEndProject2 => GetText("SolutionFiles.MissingEndProject2.sln");
......@@ -125,6 +126,8 @@ public static class CSharp
public static string ExternAlias => GetText("ProjectFiles.CSharp.ExternAlias.csproj");
public static string ExternAlias2 => GetText("ProjectFiles.CSharp.ExternAlias2.csproj");
public static string ForEmittedOutput => GetText("ProjectFiles.CSharp.ForEmittedOutput.csproj");
public static string Issue30174_InspectedLibrary => GetText("Issue30174.InspectedLibrary.InspectedLibrary.csproj");
public static string Issue30174_ReferencedLibrary => GetText("Issue30174.ReferencedLibrary.ReferencedLibrary.csproj");
public static string MsbuildError => GetText("ProjectFiles.CSharp.MsbuildError.csproj");
public static string MallformedAdditionalFilePath => GetText("ProjectFiles.CSharp.MallformedAdditionalFilePath.csproj");
public static string NetCoreApp2_Project => GetText("NetCoreApp2.Project.csproj");
......@@ -186,6 +189,8 @@ public static class CSharp
public static string CSharpClass_WithConditionalAttributes => GetText("SourceFiles.CSharp.CSharpClass_WithConditionalAttributes.cs");
public static string CSharpConsole => GetText("SourceFiles.CSharp.CSharpConsole.cs");
public static string CSharpExternAlias => GetText("SourceFiles.CSharp.CSharpExternAlias.cs");
public static string Issue30174_InspectedClass => GetText("Issue30174.InspectedLibrary.InspectedClass.cs");
public static string Issue30174_SomeMetadataAttribute => GetText("Issue30174.ReferencedLibrary.SomeMetadataAttribute.cs");
public static string NetCoreApp2_Program => GetText("NetCoreApp2.Program.cs");
public static string NetCoreApp2AndLibrary_Class1 => GetText("NetCoreApp2AndLibrary.Class1.cs");
public static string NetCoreApp2AndLibrary_Program => GetText("NetCoreApp2AndLibrary.Program.cs");
......
......@@ -90,6 +90,7 @@ protected void CreateCSharpFiles()
protected FileSet GetBaseFiles()
{
return new FileSet(
(@"NuGet.Config", Resources.NuGet_Config),
(@"Directory.Build.props", Resources.Directory_Build_props),
(@"Directory.Build.targets", Resources.Directory_Build_targets));
}
......
......@@ -3517,13 +3517,12 @@ public async Task TestOpenProject_CommandLineArgsHaveNoErrors()
var projectFilePath = GetSolutionFileName(@"CSharpProject\CSharpProject.csproj");
var properties = ImmutableDictionary<string, string>.Empty;
var buildManager = new ProjectBuildManager();
buildManager.Start();
var buildManager = new ProjectBuildManager(ImmutableDictionary<string, string>.Empty);
buildManager.StartBatchBuild();
var projectFile = await loader.LoadProjectFileAsync(projectFilePath, properties, buildManager, CancellationToken.None);
var projectFile = await loader.LoadProjectFileAsync(projectFilePath, buildManager, CancellationToken.None);
var projectFileInfo = (await projectFile.GetProjectFileInfosAsync(CancellationToken.None)).Single();
buildManager.Stop();
buildManager.EndBatchBuild();
var commandLineParser = workspace.Services
.GetLanguageServices(loader.Language)
......
......@@ -7,6 +7,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.UnitTests;
using Microsoft.CodeAnalysis.UnitTests.TestFiles;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
......@@ -22,7 +23,7 @@ public NetCoreTests()
_nugetCacheDir = SolutionDirectory.CreateDirectory(".packages");
}
private void DotNetRestore(string solutionOrProjectFileName)
private void RunDotNet(string arguments)
{
Assert.NotNull(DotNetCoreSdk.ExePath);
......@@ -32,12 +33,29 @@ private void DotNetRestore(string solutionOrProjectFileName)
};
var restoreResult = ProcessUtilities.Run(
fileName: DotNetCoreSdk.ExePath,
arguments: $@"msbuild ""{solutionOrProjectFileName}"" /t:restore /bl:{Path.Combine(SolutionDirectory.Path, "restore.binlog")}",
DotNetCoreSdk.ExePath, arguments,
workingDirectory: SolutionDirectory.Path,
additionalEnvironmentVars: environmentVariables);
Assert.True(restoreResult.ExitCode == 0, $"Restore failed with exit code {restoreResult.ExitCode}: {restoreResult.Output}");
Assert.True(restoreResult.ExitCode == 0, $"{DotNetCoreSdk.ExePath} failed with exit code {restoreResult.ExitCode}: {restoreResult.Output}");
}
private void DotNetRestore(string solutionOrProjectFileName)
{
var arguments = $@"msbuild ""{solutionOrProjectFileName}"" /t:restore /bl:{Path.Combine(SolutionDirectory.Path, "restore.binlog")}";
RunDotNet(arguments);
}
private void DotNetBuild(string solutionOrProjectFileName, string configuration = null)
{
var arguments = $@"msbuild ""{solutionOrProjectFileName}"" /bl:{Path.Combine(SolutionDirectory.Path, "build.binlog")}";
if (configuration != null)
{
arguments += $" /p:Configuration={configuration}";
}
RunDotNet(arguments);
}
[ConditionalFact(typeof(VisualStudioMSBuildInstalled), typeof(DotNetCoreSdk.IsAvailable))]
......@@ -347,5 +365,37 @@ public async Task TestOpenSolution_NetCoreMultiTFMWithProjectReferenceToFSharp()
}
}
}
[ConditionalFact(typeof(VisualStudioMSBuildInstalled), typeof(DotNetCoreSdk.IsAvailable))]
[Trait(Traits.Feature, Traits.Features.MSBuildWorkspace)]
[Trait(Traits.Feature, Traits.Features.NetCore)]
public async Task TestOpenProject_ReferenceConfigurationSpecificMetadata()
{
var files = GetBaseFiles()
.WithFile(@"Solution.sln", Resources.SolutionFiles.Issue30174_Solution)
.WithFile(@"InspectedLibrary\InspectedLibrary.csproj", Resources.ProjectFiles.CSharp.Issue30174_InspectedLibrary)
.WithFile(@"InspectedLibrary\InspectedClass.cs", Resources.SourceFiles.CSharp.Issue30174_InspectedClass)
.WithFile(@"ReferencedLibrary\ReferencedLibrary.csproj", Resources.ProjectFiles.CSharp.Issue30174_ReferencedLibrary)
.WithFile(@"ReferencedLibrary\SomeMetadataAttribute.cs", Resources.SourceFiles.CSharp.Issue30174_SomeMetadataAttribute);
CreateFiles(files);
DotNetRestore("Solution.sln");
DotNetBuild("Solution.sln", configuration: "Release");
var projectFilePath = GetSolutionFileName(@"InspectedLibrary\InspectedLibrary.csproj");
using (var workspace = CreateMSBuildWorkspace(("Configuration", "Release")))
{
workspace.LoadMetadataForReferencedProjects = true;
var project = await workspace.OpenProjectAsync(projectFilePath);
Assert.Empty(project.ProjectReferences);
Assert.Empty(workspace.Diagnostics);
var compilation = await project.GetCompilationAsync();
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册