diff options
author | Mikayla Hutchinson <m.j.hutchinson@gmail.com> | 2017-06-01 19:26:13 +0300 |
---|---|---|
committer | Mikayla Hutchinson <m.j.hutchinson@gmail.com> | 2017-06-01 21:43:11 +0300 |
commit | 049317310c15244edca81c8716d1e0147b56728d (patch) | |
tree | 3df5e082341896c7a61d3dac26553874ea7cb636 | |
parent | cc461bffe09dfd9ad5d524793ff1e89a3ecf3bc9 (diff) |
[Project] Unify getting project and assembly referencesmonodevelop-pr-2445
31 files changed, 757 insertions, 647 deletions
diff --git a/main/external/fsharpbinding/MonoDevelop.FSharpBinding/MonoDevelop.FSharp.fsproj b/main/external/fsharpbinding/MonoDevelop.FSharpBinding/MonoDevelop.FSharp.fsproj index 34870659e2..89065c3362 100644 --- a/main/external/fsharpbinding/MonoDevelop.FSharpBinding/MonoDevelop.FSharp.fsproj +++ b/main/external/fsharpbinding/MonoDevelop.FSharpBinding/MonoDevelop.FSharp.fsproj @@ -156,11 +156,6 @@ <Private>False</Private> <HintPath>..\..\..\build\bin\Xwt.Gtk.dll</HintPath> </Reference> - <ProjectReference Include="..\..\..\src\core\MonoDevelop.Projects.Formats.MSBuild\MonoDevelop.Projects.Formats.MSBuild.csproj"> - <Project>{A437F1A3-78DF-4F00-8053-D32A8B1EB679}</Project> - <Name>MonoDevelop.Projects.Formats.MSBuild</Name> - <Private>False</Private> - </ProjectReference> <Reference Include="monodoc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" /> <ProjectReference Include="..\MonoDevelop.FSharp.Gui\MonoDevelop.FSharp.Gui.csproj"> <Project>{FD0D1033-9145-48E5-8ED8-E2365252878C}</Project> @@ -369,4 +364,4 @@ </When> </Choose> <Import Project="..\packages\StrongNamer\build\StrongNamer.targets" Condition="Exists('..\packages\StrongNamer\build\StrongNamer.targets')" Label="Paket" /> -</Project>
\ No newline at end of file +</Project> diff --git a/main/src/addins/AspNet/Projects/AspNetAppProjectFlavor.cs b/main/src/addins/AspNet/Projects/AspNetAppProjectFlavor.cs index bffd2966e8..3f84f5926a 100644 --- a/main/src/addins/AspNet/Projects/AspNetAppProjectFlavor.cs +++ b/main/src/addins/AspNet/Projects/AspNetAppProjectFlavor.cs @@ -154,7 +154,6 @@ namespace MonoDevelop.AspNet.Projects BaseDirectory = Project.BaseDirectory, TargetRuntime = Project.TargetRuntime, TargetFramework = Project.TargetFramework, - UserAssemblyPaths = Project.GetUserAssemblyPaths (config), EnvironmentVariables = configuration.EnvironmentVariables, }; } @@ -170,9 +169,11 @@ namespace MonoDevelop.AspNet.Projects //check XSP is available var cfg = GetConfiguration (configuration); - var cmd = CreateExecutionCommand (configuration, cfg); + var cmd = (AspNetExecutionCommand) CreateExecutionCommand (configuration, cfg); var browserExcTarget = context.ExecutionTarget as BrowserExecutionTarget; + cmd.UserAssemblyPaths = await Project.GetUserAssemblyPaths (configuration, monitor.CancellationToken); + OperationConsole console = null; bool isXsp = true; //FIXME: fix this when it might not be true - should delegate to the ExecutionHandler @@ -627,21 +628,6 @@ namespace MonoDevelop.AspNet.Projects return files; } - protected override void OnPopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration) - { - base.OnPopulateSupportFileList (list, configuration); - - //HACK: workaround for MD not local-copying package references - foreach (MonoDevelop.Projects.ProjectReference projectReference in Project.References) { - if (projectReference.Package != null && projectReference.Package.Name == "system.web.mvc") { - if (projectReference.ReferenceType == ReferenceType.Package) - foreach (SystemAssembly assem in projectReference.Package.Assemblies) - list.Add (assem.Location); - break; - } - } - } - public string GetAspNetMvcVersion () { foreach (var pref in Project.References) { diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs index 3b6554e7be..48de841b19 100644 --- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs +++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs @@ -2,7 +2,9 @@ using System; using System.IO; using MonoDevelop.Projects; +using MonoDevelop.Projects.MSBuild; using MonoDevelop.Core; +using System.Linq; namespace MonoDevelop.Deployment { @@ -24,13 +26,28 @@ namespace MonoDevelop.Deployment // Add the compiled output files ProjectConfiguration pconf = (ProjectConfiguration) project.GetConfiguration (configuration); - FilePath outDir = pconf.OutputDirectory; - foreach (FilePath file in project.GetOutputFiles (configuration)) { - deployFiles.Add (new DeployFile (project, file, file.ToRelative (outDir), TargetDirectory.ProgramFiles)); + + var evalCtx = new TargetEvaluationContext (); + evalCtx.ItemsToEvaluate.Add ("AllPublishItemsFullPathWithTargetPath"); + + bool useMSBuild = !project.MSBuildEngineSupport.HasFlag (MSBuildSupport.NotSupported); + if (useMSBuild) { + var result = project.RunTarget (null, "GetCopyToPublishDirectoryItems", configuration, evalCtx).Result; + foreach (var item in result.Items) { + if (item.Name == "AllPublishItemsFullPathWithTargetPath") { + var fromPath = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, item.Include); + var toPath = item.Metadata.GetPathValue ("TargetPath", relativeToPath: pconf.OutputDirectory); + deployFiles.Add (new DeployFile (project, fromPath, toPath, TargetDirectory.ProgramFiles)); + } + } + } else { +#pragma warning disable 618 + foreach (FileCopySet.Item item in project.GetSupportFileList (configuration)) { + deployFiles.Add (new DeployFile (project, item.Src, item.Target, TargetDirectory.ProgramFiles)); + } +#pragma warning restore 618 } -// FilePath outputFile = project.GetOutputFileName (configuration); - // Collect deployable files foreach (ProjectFile file in project.Files) { // skip CopyToOutputDirectory files when it's just a project build, because @@ -45,11 +62,7 @@ namespace MonoDevelop.Deployment deployFiles.Add (dp); } } - - foreach (FileCopySet.Item item in project.GetSupportFileList (configuration)) { - deployFiles.Add (new DeployFile (project, item.Src, item.Target, TargetDirectory.ProgramFiles)); - } - + return deployFiles; } } diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserViewContent.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserViewContent.cs index ef94e81fb5..7502b215fa 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserViewContent.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserViewContent.cs @@ -170,8 +170,8 @@ namespace MonoDevelop.AssemblyBrowser var netProject = project as DotNetProject; if (netProject == null) continue; - foreach (var file in await netProject.GetReferencedAssemblies (ConfigurationSelector.Default, false)) { - if (!System.IO.File.Exists (file.FilePath)) + foreach (var file in await netProject.GetReferences (ConfigurationSelector.Default)) { + if (file.IsProjectReference || !System.IO.File.Exists (file.FilePath)) continue; Widget.AddReferenceByFileName (file.FilePath); } diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs index f1ada4ce17..36993b73ab 100644 --- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs +++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs @@ -437,12 +437,6 @@ namespace MonoDevelop.GtkCore.GuiBuilder monitor.Log.WriteLine (GettextCatalog.GetString ("Generating GUI code for project '{0}'...", project.Name)); - timer.Trace ("Copy support files"); - - // Make sure the referenced assemblies are up to date. It is necessary to do - // it now since they may contain widget libraries. - project.CopySupportFiles (monitor, configuration); - timer.Trace ("Update libraries"); info.GuiBuilderProject.UpdateLibraries (); diff --git a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/CreateNuGetPackageBuildTarget.cs b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/CreateNuGetPackageBuildTarget.cs index 85df6eeaba..6bfe84bc2d 100644 --- a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/CreateNuGetPackageBuildTarget.cs +++ b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/CreateNuGetPackageBuildTarget.cs @@ -66,7 +66,7 @@ namespace MonoDevelop.Packaging var result = new BuildResult (); // Build the project and any dependencies first. - if (buildReferencedTargets && project.GetReferencedItems (configuration).Any ()) {
+ if (buildReferencedTargets && (await project.GetReferencedItems (configuration, monitor.CancellationToken)).Any ()) {
result = await project.Build (monitor, configuration, buildReferencedTargets, operationContext); if (result.Failed) return result; diff --git a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/PackagingProject.cs b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/PackagingProject.cs index d0b8730e05..56aefbae1d 100644 --- a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/PackagingProject.cs +++ b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging/PackagingProject.cs @@ -117,16 +117,9 @@ namespace MonoDevelop.Packaging return true; } - protected override bool OnGetCanExecute (Projects.ExecutionContext context, ConfigurationSelector configuration, SolutionItemRunConfiguration runConfiguration) + protected override ProjectFeatures OnGetSupportedFeatures () { - return false; - } - - protected override void PopulateOutputFileList ( - List<FilePath> list, - ConfigurationSelector configuration) - { - list.Add (OnGetOutputFileName (configuration)); + return base.OnGetSupportedFeatures () | ~ProjectFeatures.Execute; } protected override void OnPrepareForEvaluation (MSBuildProject project) diff --git a/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitAssemblyTestSuite.cs b/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitAssemblyTestSuite.cs index d018440022..6bdb49a3ab 100644 --- a/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitAssemblyTestSuite.cs +++ b/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitAssemblyTestSuite.cs @@ -58,6 +58,7 @@ namespace MonoDevelop.UnitTesting.NUnit static Queue<LoadData> loadQueue = new Queue<LoadData> (); static bool loaderRunning; + [Obsolete("This will be removed in future releases")] public virtual IList<string> UserAssemblyPaths { get { return null; diff --git a/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitProjectTestSuite.cs b/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitProjectTestSuite.cs index 1d88381efb..4cee001b7e 100644 --- a/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitProjectTestSuite.cs +++ b/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitProjectTestSuite.cs @@ -52,6 +52,7 @@ namespace MonoDevelop.UnitTesting.NUnit string resultsPath; string storeId; + [Obsolete ("This will be removed in future releases")] public override IList<string> UserAssemblyPaths { get { return project.GetUserAssemblyPaths (IdeApp.Workspace.ActiveConfiguration); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteProjectBuilder.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteProjectBuilder.cs index d7dc6b5e31..23664fe20f 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteProjectBuilder.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteProjectBuilder.cs @@ -372,7 +372,7 @@ namespace MonoDevelop.Projects.MSBuild } } - public async Task<AssemblyReference[]> ResolveAssemblyReferences (ProjectConfigurationInfo[] configurations, Dictionary<string, string> globalProperties, CancellationToken cancellationToken) + public async Task<AssemblyReference[]> ResolveReferences (ProjectConfigurationInfo[] configurations, Dictionary<string, string> globalProperties, CancellationToken cancellationToken) { AssemblyReference[] refs = null; var id = configurations [0].Configuration + "|" + configurations [0].Platform; @@ -390,24 +390,23 @@ namespace MonoDevelop.Projects.MSBuild try { BeginOperation (); result = await builder.Run ( - configurations, -1, MSBuildEvent.None, MSBuildVerbosity.Quiet, - new [] { "ResolveAssemblyReferences" }, new [] { "ReferencePath" }, null, globalProperties, taskId + configurations, -1, MSBuildEvent.None, MSBuildVerbosity.Quiet, + new [] { "ResolveReferences" }, new [] { "ReferencePath" }, null, globalProperties, taskId ).ConfigureAwait (false); } catch (Exception ex) { await CheckDisconnected ().ConfigureAwait (false); - LoggingService.LogError ("ResolveAssemblyReferences failed", ex); + LoggingService.LogError ("ResolveReferences failed", ex); return new AssemblyReference [0]; } finally { cr.Dispose (); EndOperation (); } - MSBuildEvaluatedItem[] items; - if (result.Items.TryGetValue ("ReferencePath", out items) && items != null) { - string aliases; - refs = items.Select (i => new AssemblyReference (i.ItemSpec, i.Metadata.TryGetValue ("Aliases", out aliases) ? aliases : "")).ToArray (); - } else + if (result.Items.TryGetValue ("ReferencePath", out MSBuildEvaluatedItem [] items) && items != null) { + refs = items.Select (i => new AssemblyReference (i.ItemSpec, i.Metadata)).ToArray (); + } else { refs = new AssemblyReference [0]; + } referenceCache [id] = refs; } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/AssemblyReference.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/AssemblyReference.cs index 32fd00e97c..aa56bf915e 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/AssemblyReference.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/AssemblyReference.cs @@ -26,20 +26,65 @@ using System; using System.Collections.Generic; using MonoDevelop.Core; -using System.Linq; namespace MonoDevelop.Projects { public sealed class AssemblyReference { + Dictionary<string, string> metadata; + + [Obsolete] public AssemblyReference (FilePath path, string aliases = null) { FilePath = path; - Aliases = aliases ?? ""; + metadata = new Dictionary<string, string> { { "Aliases", aliases } }; + } + + public AssemblyReference (FilePath path, Dictionary<string, string> metadata) + { + FilePath = path; + this.metadata = metadata; } public FilePath FilePath { get; private set; } - public string Aliases { get; private set; } + + public string Aliases => GetMetadata ("Aliases") ?? ""; + + /// <summary> + /// Whether the reference is a project. + /// </summary> + public bool IsProjectReference => GetMetadata ("ReferenceSourceTarget") == "ProjectReference"; + + /// <summary> + /// For project references, true if the output assembly should be referenced. + /// </summary> + public bool ReferenceOutputAssembly => MetadataIsTrue ("ReferenceOutputAssembly"); + + /// <summary> + /// True if the assembly reference was added implicitly]. + /// </summary> + public bool IsImplicit => MetadataIsTrue ("Implicit"); + + /// <summary> + /// True if the assembly will be copied to the output directory. + /// </summary> + public bool IsCopyLocal => MetadataIsTrue ("CopyLocal"); + + /// <summary> + /// True if the assembly is from the target framework. + /// </summary> + public bool IsFrameworkFile => MetadataIsTrue ("FrameworkFile"); + + public string GetMetadata (string name) + { + metadata.TryGetValue (name, out string value); + return value; + } + + public bool MetadataIsTrue (string name) + { + return string.Equals (GetMetadata (name), "true", StringComparison.OrdinalIgnoreCase); + } public override bool Equals (object obj) { @@ -61,5 +106,25 @@ namespace MonoDevelop.Projects { return Aliases.Split (new [] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); } + + public SolutionItem GetReferencedItem (Solution parentSolution) + { + var projectPath = GetMetadata ("MSBuildSourceProjectFile"); + if (!string.IsNullOrEmpty (projectPath)) { + var project = parentSolution.FindSolutionItem (projectPath); + if (project != null) { + return project; + } + } + + var projectGuid = GetMetadata ("Project"); + if (!string.IsNullOrEmpty (projectGuid)) { + if (parentSolution.GetSolutionItem (projectGuid) is SolutionItem item) { + return item; + } + } + + return null; + } } }
\ No newline at end of file diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs index d162f4eea3..0330b62d55 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs @@ -26,24 +26,20 @@ // using System; -using System.Linq; -using System.Text; -using System.Collections; using System.Collections.Generic; +using System.Collections.Immutable; +using System.Globalization; using System.IO; -using System.Xml; +using System.Linq; +using System.Text; using System.Threading; +using System.Threading.Tasks; +using System.Xml; using MonoDevelop.Core; +using MonoDevelop.Core.Assemblies; using MonoDevelop.Core.Execution; -using MonoDevelop.Projects.Policies; -using MonoDevelop.Projects.MD1; -using MonoDevelop.Projects.Extensions; using MonoDevelop.Projects.MSBuild; -using MonoDevelop.Core.Assemblies; -using System.Globalization; -using System.Threading.Tasks; -using System.Collections.Immutable; -using MonoDevelop.Projects.MSBuild.Conditions; +using MonoDevelop.Projects.Policies; namespace MonoDevelop.Projects { @@ -340,7 +336,7 @@ namespace MonoDevelop.Projects public LanguageBinding LanguageBinding { get { if (languageBinding == null) { - languageBinding = FindLanguage (languageName); + languageBinding = LanguageBindingService.GetBindingPerLanguageName (languageName); //older projects may not have this property but may not support partial types //so need to verify that the default attribute is OK @@ -641,6 +637,7 @@ namespace MonoDevelop.Projects [ThreadStatic] static HashSet<DotNetProject> processedProjects; + [Obsolete] internal protected override void PopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration) { try { @@ -656,6 +653,7 @@ namespace MonoDevelop.Projects } } + [Obsolete] void PopulateSupportFileListInternal (FileCopySet list, ConfigurationSelector configuration) { if (supportReferDistance <= 2) @@ -733,6 +731,7 @@ namespace MonoDevelop.Projects //a valid culture //Note: hand-written as this can get called lotsa times //Note: code duplicated in prj2make/Utils.cs as TrySplitResourceName + [Obsolete] internal static string GetResourceCulture (string fname) { int last_dot = -1; @@ -779,6 +778,7 @@ namespace MonoDevelop.Projects } } + [Obsolete] IEnumerable<string> GetAssemblyRefsRec (string fileName, HashSet<string> visited) { // Recursivelly finds assemblies referenced by the given assembly @@ -823,22 +823,22 @@ namespace MonoDevelop.Projects return newReferenceInformation; } - protected override IEnumerable<SolutionItem> OnGetReferencedItems (ConfigurationSelector configuration) + protected override async Task<List<SolutionItem>> OnGetReferencedItems (ConfigurationSelector configuration, CancellationToken token) { - var items = new List<SolutionItem> (base.OnGetReferencedItems (configuration)); - if (ParentSolution == null) - return items; + var result = new List<SolutionItem> (); + if (ParentSolution == null) { + return result; + } - var ctx = new ProjectParserContext (this, (DotNetProjectConfiguration)GetConfiguration (configuration)); - foreach (ProjectReference pref in References) { - if (pref.ReferenceType == ReferenceType.Project && - (string.IsNullOrEmpty (pref.Condition) || ConditionParser.ParseAndEvaluate (pref.Condition, ctx))) { - Project rp = pref.ResolveProject (ParentSolution); - if (rp != null) - items.Add (rp); + foreach (var reference in await GetReferences (configuration, token)) { + if (reference.IsProjectReference) { + var item = reference.GetReferencedItem (ParentSolution); + if (item != null) { + result.Add (item); + } } } - return items; + return result; } /// <summary> @@ -866,64 +866,99 @@ namespace MonoDevelop.Projects public Task<IEnumerable<AssemblyReference>> GetReferencedAssemblies (ConfigurationSelector configuration, bool includeProjectReferences) { return BindTask<IEnumerable<AssemblyReference>> (async ct => { - var res = await ProjectExtension.OnGetReferencedAssemblies (configuration); - - if (includeProjectReferences) { - foreach (ProjectReference pref in References.Where (pr => pr.ReferenceType == ReferenceType.Project)) { - foreach (var asm in pref.GetReferencedFileNames (configuration)) - res.Add (new AssemblyReference (asm, pref.Aliases)); + var result = new List<AssemblyReference> (); + var res = await GetReferences (configuration); + + foreach (var r in await OnGetReferences (configuration, ct).ConfigureAwait (false)) { + if (includeProjectReferences || ! r.IsProjectReference) { + result.Add (r); } } - return res; + return result; + }); + } + + public Task<List<AssemblyReference>> GetReferences (ConfigurationSelector configuration) + { + return BindTask (async ct => { + return await ProjectExtension.OnGetReferences (configuration, ct); }); } + public Task<List<AssemblyReference>> GetReferences (ConfigurationSelector configuration, CancellationToken token) + { + return ProjectExtension.OnGetReferences (configuration, token); + } + /// <summary> /// Gets the referenced assembly projects, but only projects which output are actually referenced /// for example references with ReferenceOutputAssembly=false are excluded /// </summary> /// <param name="configuration">Configuration.</param> + public async Task<List<DotNetProject>> GetReferencedAssemblyProjects (ConfigurationSelector configuration, CancellationToken token) + { + var result = new List<DotNetProject> (); + if (ParentSolution == null){ + return result; + } + + foreach (var r in await OnGetReferences (configuration, token).ConfigureAwait (false)) { + if (r.IsProjectReference && r.ReferenceOutputAssembly && r.GetReferencedItem (ParentSolution) is DotNetProject p) { + result.Add (p); + } + } + return result; + } + + [Obsolete("Use overload that returns a Task")] public IEnumerable<DotNetProject> GetReferencedAssemblyProjects (ConfigurationSelector configuration) { - return ProjectExtension.OnGetReferencedAssemblyProjects (configuration); + return GetReferencedAssemblyProjects (configuration, CancellationToken.None).Result; } internal protected virtual async Task<List<AssemblyReference>> OnGetReferencedAssemblies (ConfigurationSelector configuration) { - List<AssemblyReference> result = new List<AssemblyReference> (); - if (CheckUseMSBuildEngine (configuration)) { - // Get the references list from the msbuild project - RemoteProjectBuilder builder = await GetProjectBuilder (); - try { - var configs = GetConfigurations (configuration, false); - var globalProperties = CreateGlobalProperties (); - - AssemblyReference [] refs; - using (Counters.ResolveMSBuildReferencesTimer.BeginTiming (GetProjectEventMetadata (configuration))) - refs = await builder.ResolveAssemblyReferences (configs, globalProperties, CancellationToken.None); - foreach (var r in refs) - result.Add (r); - } finally { - builder.ReleaseReference (); + var result = new List<AssemblyReference> (); + foreach (var r in await OnGetReferences (configuration, CancellationToken.None).ConfigureAwait (false)) { + if (!r.IsProjectReference) { + result.Add (r); } - } else { - foreach (ProjectReference pref in References) { - if (pref.ReferenceType != ReferenceType.Project) { - foreach (string asm in pref.GetReferencedFileNames (configuration)) - result.Add (new AssemblyReference (asm, pref.Aliases)); + } + return result; + } + + [Obsolete] + async Task<List<AssemblyReference>> GetReferencedAssembliesDeprecated (ConfigurationSelector configuration) + { + var result = new List<AssemblyReference> (); + + var ctx = new MD1.ProjectParserContext (this, (DotNetProjectConfiguration)GetConfiguration (configuration)); + foreach (ProjectReference pref in References) { + if (!string.IsNullOrEmpty (pref.Condition) && !MSBuild.Conditions.ConditionParser.ParseAndEvaluate (pref.Condition, ctx)) + continue; + + foreach (string asm in pref.GetReferencedFileNames (configuration)) { + var metadata = new Dictionary<string, string> { { "Aliases", pref.Aliases } }; + if (pref.ReferenceType == ReferenceType.Project) { + var refProj = ParentSolution != null ? pref.ResolveProject (ParentSolution) : null; + if (refProj != null) { + metadata ["MSBuildSourceProjectFile"] = refProj.FileName; + } } + result.Add (new AssemblyReference (asm, pref.Aliases)); } - var mscorlib = AssemblyContext.GetAssemblyFullName ("mscorlib", TargetFramework); - var mscorlibPath = AssemblyContext.GetAssemblyLocation (mscorlib, TargetFramework); - if (!result.Any (ar => ar.FilePath == mscorlibPath)) - result.Add (new AssemblyReference (mscorlibPath)); - - var core = AssemblyContext.GetAssemblyFullName ("System.Core", TargetFramework); - var corePath = AssemblyContext.GetAssemblyLocation (core, TargetFramework); - if (!string.IsNullOrEmpty (corePath)) { - if (!result.Any (ar => ar.FilePath == corePath)) - result.Add (new AssemblyReference (corePath)); - } + } + + var mscorlib = AssemblyContext.GetAssemblyFullName ("mscorlib", TargetFramework); + var mscorlibPath = AssemblyContext.GetAssemblyLocation (mscorlib, TargetFramework); + if (!result.Any (ar => ar.FilePath == mscorlibPath)) + result.Add (new AssemblyReference (mscorlibPath)); + + var core = AssemblyContext.GetAssemblyFullName ("System.Core", TargetFramework); + var corePath = AssemblyContext.GetAssemblyLocation (core, TargetFramework); + if (!string.IsNullOrEmpty (corePath)) { + if (!result.Any (ar => ar.FilePath == corePath)) + result.Add (new AssemblyReference (corePath)); } var config = (DotNetProjectConfiguration)GetConfiguration (configuration); @@ -974,9 +1009,11 @@ namespace MonoDevelop.Projects result.Add (ar); } } + return result; } + public Task<IEnumerable<PackageDependency>> GetPackageDependencies (ConfigurationSelector configuration, CancellationToken cancellationToken) { return BindTask<IEnumerable<PackageDependency>> (async ct => { @@ -987,51 +1024,81 @@ namespace MonoDevelop.Projects internal protected virtual async Task<List<PackageDependency>> OnGetPackageDependencies (ConfigurationSelector configuration, CancellationToken cancellationToken) { var result = new List<PackageDependency> (); - if (CheckUseMSBuildEngine (configuration)) { - // Get the references list from the msbuild project - RemoteProjectBuilder builder = await GetProjectBuilder (); - try { - var configs = GetConfigurations (configuration, false); - var globalProperties = CreateGlobalProperties (); - - PackageDependency [] dependencies; - using (Counters.ResolveMSBuildReferencesTimer.BeginTiming (GetProjectEventMetadata (configuration))) - dependencies = await builder.ResolvePackageDependencies (configs, globalProperties, cancellationToken); - foreach (var d in dependencies) - result.Add (d); - } finally { - builder.ReleaseReference (); - } + if (!CheckUseMSBuildEngine (configuration)) { + return result; + } + + // Get the references list from the msbuild project + RemoteProjectBuilder builder = await GetProjectBuilder (); + try { + var configs = await GetConfigurations (configuration, false); + var globalProperties = CreateGlobalProperties (); + + PackageDependency [] dependencies; + using (Counters.ResolveMSBuildReferencesTimer.BeginTiming (GetProjectEventMetadata (configuration))) + dependencies = await builder.ResolvePackageDependencies (configs, globalProperties, cancellationToken); + foreach (var d in dependencies) + result.Add (d); + } finally { + builder.ReleaseReference (); } + return result; } + [Obsolete("Use MSBuild")] internal protected virtual IEnumerable<DotNetProject> OnGetReferencedAssemblyProjects (ConfigurationSelector configuration) { if (ParentSolution == null) { yield break; } - var ctx = new ProjectParserContext (this, (DotNetProjectConfiguration)GetConfiguration (configuration)); - foreach (ProjectReference pref in References) { - if (pref.ReferenceType == ReferenceType.Project && pref.ReferenceOutputAssembly && - (string.IsNullOrEmpty (pref.Condition) || ConditionParser.ParseAndEvaluate (pref.Condition, ctx))) { - var rp = pref.ResolveProject (ParentSolution) as DotNetProject; - if (rp != null) - yield return rp; + + foreach (var reference in GetReferences (configuration).Result) { + if (reference.IsProjectReference) { + var item = reference.GetReferencedItem (ParentSolution); + if (item is DotNetProject p) { + yield return p; + } } } } - protected override Task<BuildResult> DoBuild (ProgressMonitor monitor, ConfigurationSelector configuration) + internal protected virtual async Task<List<AssemblyReference>> OnGetReferences (ConfigurationSelector configuration, CancellationToken token) { - var handler = new MD1DotNetProjectHandler (this); - return handler.RunTarget (monitor, "Build", configuration); + if (!CheckUseMSBuildEngine (configuration)) { +#pragma warning disable 618 + return await OnGetReferencesDeprecated (configuration); +#pragma warning restore 618 + } + + RemoteProjectBuilder builder = await GetProjectBuilder (); + try { + var configs = await GetConfigurations (configuration, false); + var globalProperties = CreateGlobalProperties (); + + using (Counters.ResolveMSBuildReferencesTimer.BeginTiming (GetProjectEventMetadata (configuration))) { + var refs = await builder.ResolveReferences (configs, globalProperties, CancellationToken.None); + return new List<AssemblyReference> (refs); + } + } finally { + builder.ReleaseReference (); + } } - protected override Task<BuildResult> DoClean (ProgressMonitor monitor, ConfigurationSelector configuration) + [Obsolete] + async Task<List<AssemblyReference>> OnGetReferencesDeprecated (ConfigurationSelector configuration) { - var handler = new MD1DotNetProjectHandler (this); - return handler.RunTarget (monitor, "Clean", configuration); + var list = await GetReferencedAssembliesDeprecated (configuration); + + var items = new List<SolutionItem> (base.OnGetReferencedItems (configuration)); + foreach (var item in items.OfType<Project> ()) { + list.Add (new AssemblyReference ( + item.GetOutputFileName (configuration), + new Dictionary<string, string> { { "MSBuildSourceProjectFile", item.FileName } } + )); + } + + return list; } protected internal override Task OnSave (ProgressMonitor monitor) @@ -1043,11 +1110,6 @@ namespace MonoDevelop.Projects return base.OnSave (monitor); } - LanguageBinding FindLanguage (string name) - { - return LanguageBindingService.GetBindingPerLanguageName (languageName); - } - protected override SolutionItemConfiguration OnCreateConfiguration (string name, ConfigurationKind kind) { DotNetProjectConfiguration conf = new DotNetProjectConfiguration (name); @@ -1087,6 +1149,7 @@ namespace MonoDevelop.Projects return null; } + [Obsolete] protected override bool CheckNeedsBuild (ConfigurationSelector configuration) { if (base.CheckNeedsBuild (configuration)) @@ -1125,9 +1188,10 @@ namespace MonoDevelop.Projects var config = (DotNetProjectConfiguration) GetConfiguration (configuration); return Files.Any (file => file.BuildAction == BuildAction.EmbeddedResource && String.Compare (Path.GetExtension (file.FilePath), ".resx", StringComparison.OrdinalIgnoreCase) == 0 - && MD1DotNetProjectHandler.IsResgenRequired (file.FilePath, config.IntermediateOutputDirectory.Combine (file.ResourceId))); + && MD1.MD1DotNetProjectHandler.IsResgenRequired (file.FilePath, config.IntermediateOutputDirectory.Combine (file.ResourceId))); } + [Obsolete] protected internal override DateTime OnGetLastBuildTime (ConfigurationSelector configuration) { var outputBuildTime = base.OnGetLastBuildTime (configuration); @@ -1168,13 +1232,20 @@ namespace MonoDevelop.Projects return exeFile + ".mdb"; } + [Obsolete ("Use the overload that returns a Task")] public IList<string> GetUserAssemblyPaths (ConfigurationSelector configuration) { + return GetUserAssemblyPaths (configuration, CancellationToken.None).Result;; + } + + public async Task<IList<string>> GetUserAssemblyPaths (ConfigurationSelector configuration, CancellationToken token) + { if (ParentSolution == null) return null; //return all projects in the sln in case some are loaded dynamically //FIXME: should we do this for the whole workspace? - return ParentSolution.RootFolder.GetAllBuildableEntries (configuration).OfType<DotNetProject> () + var entries = await ParentSolution.RootFolder.GetAllBuildableEntries (configuration, token).ConfigureAwait (false); + return entries.OfType<DotNetProject> () .Select (d => (string) d.GetOutputFileName (configuration)) .Where (d => !string.IsNullOrEmpty (d)).ToList (); } @@ -1336,14 +1407,16 @@ namespace MonoDevelop.Projects return baseFiles; } + [Obsolete] internal Task<BuildResult> Compile (ProgressMonitor monitor, BuildData buildData) { return ProjectExtension.OnCompile (monitor, buildData); } + [Obsolete] protected virtual Task<BuildResult> OnCompile (ProgressMonitor monitor, BuildData buildData) { - return MD1DotNetProjectHandler.Compile (monitor, this, buildData); + return MD1.MD1DotNetProjectHandler.Compile (monitor, this, buildData); } protected override bool OnGetIsCompileable (string fileName) @@ -1708,7 +1781,7 @@ namespace MonoDevelop.Projects var dotNetExecutionCommand = executionCommand as DotNetExecutionCommand; if (dotNetExecutionCommand != null) {
- dotNetExecutionCommand.UserAssemblyPaths = GetUserAssemblyPaths (configuration); + dotNetExecutionCommand.UserAssemblyPaths = await GetUserAssemblyPaths (configuration, monitor.CancellationToken); externalConsole = dotNetExecutionCommand.ExternalConsole; pauseConsole = dotNetExecutionCommand.PauseConsoleOutput; } @@ -1870,22 +1943,28 @@ namespace MonoDevelop.Projects return Project.OnGetDefaultTargetPlatform (projectCreateInfo); } + internal protected override Task<List<AssemblyReference>> OnGetReferences (ConfigurationSelector configuration, CancellationToken token) + { + return Project.OnGetReferences (configuration, token); + } + + [Obsolete] internal protected override Task<List<AssemblyReference>> OnGetReferencedAssemblies (ConfigurationSelector configuration) { return Project.OnGetReferencedAssemblies (configuration); } + [Obsolete] internal protected override IEnumerable<DotNetProject> OnGetReferencedAssemblyProjects (ConfigurationSelector configuration) { return Project.OnGetReferencedAssemblyProjects (configuration); } -#pragma warning disable 672 // Member overrides obsolete member + [Obsolete] internal protected override ExecutionCommand OnCreateExecutionCommand (ConfigurationSelector configSel, DotNetProjectConfiguration configuration) { return Project.OnCreateExecutionCommand (configSel, configuration); } -#pragma warning restore 672 // Member overrides obsolete member internal protected override ExecutionCommand OnCreateExecutionCommand (ConfigurationSelector configSel, DotNetProjectConfiguration configuration, ProjectRunConfiguration runConfiguration) { @@ -1907,6 +1986,7 @@ namespace MonoDevelop.Projects Project.OnReferencedAssembliesChanged (); } + [Obsolete] internal protected override Task<BuildResult> OnCompile (ProgressMonitor monitor, BuildData buildData) { return Project.OnCompile (monitor, buildData); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectExtension.cs index bdbf68ccef..08cebb811a 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectExtension.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectExtension.cs @@ -25,11 +25,11 @@ // THE SOFTWARE. using System; using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MonoDevelop.Core; using MonoDevelop.Core.Assemblies; using MonoDevelop.Core.Execution; -using MonoDevelop.Core; -using System.Threading.Tasks; -using MonoDevelop.Projects.MSBuild; namespace MonoDevelop.Projects { @@ -72,17 +72,24 @@ namespace MonoDevelop.Projects return next.OnGetDefaultTargetPlatform (projectCreateInfo); } + internal protected virtual Task<List<AssemblyReference>> OnGetReferences (ConfigurationSelector configuration, CancellationToken token) + { + return next.OnGetReferences (configuration, token); + } + + [Obsolete ("Use MSBuild")] internal protected virtual Task<List<AssemblyReference>> OnGetReferencedAssemblies (ConfigurationSelector configuration) { return next.OnGetReferencedAssemblies (configuration); } + [Obsolete ("Use MSBuild")] internal protected virtual IEnumerable<DotNetProject> OnGetReferencedAssemblyProjects (ConfigurationSelector configuration) { return next.OnGetReferencedAssemblyProjects (configuration); } - [Obsolete("User overload that takes a RunConfiguration")] + [Obsolete("Use overload that takes a RunConfiguration")] internal protected virtual ExecutionCommand OnCreateExecutionCommand (ConfigurationSelector configSel, DotNetProjectConfiguration configuration) { return next.OnCreateExecutionCommand (configSel, configuration); @@ -135,6 +142,7 @@ namespace MonoDevelop.Projects return next.OnGetSupportsFramework (framework); } + [Obsolete("Use MSBuild")] internal protected virtual Task<BuildResult> OnCompile (ProgressMonitor monitor, BuildData buildData) { return next.OnCompile (monitor, buildData); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/PortableDotNetProjectFlavor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/PortableDotNetProjectFlavor.cs index 44bfd47bb2..d915c2664c 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/PortableDotNetProjectFlavor.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/PortableDotNetProjectFlavor.cs @@ -75,16 +75,6 @@ namespace MonoDevelop.Projects // Note: see also: PortableLibrary.xpt.xml return new TargetFrameworkMoniker (".NETPortable", "4.5", "Profile78"); } - - internal protected override async Task<List<AssemblyReference>> OnGetReferencedAssemblies (ConfigurationSelector configuration) - { - var res = await base.OnGetReferencedAssemblies (configuration); - if (Project.TargetFramework.Id.Version != "5.0") { - var asms = Project.TargetRuntime.AssemblyContext.GetAssemblies (Project.TargetFramework).Where (a => a.Package.IsFrameworkPackage).Select (a => new AssemblyReference (a.Location)); - res.AddRange (asms); - } - return res; - } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs index 1213cea236..b2dd37f775 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs @@ -1109,7 +1109,7 @@ namespace MonoDevelop.Projects { if (target == ProjectService.BuildTarget) return RunBuildTarget (monitor, configuration, context); - else if (target == ProjectService.CleanTarget) + if (target == ProjectService.CleanTarget) return RunCleanTarget (monitor, configuration, context); return RunMSBuildTarget (monitor, target, configuration, context); } @@ -1147,10 +1147,13 @@ namespace MonoDevelop.Projects } } - // Collect last write times for the files generated by this project - var fileTimes = new Dictionary<FilePath, DateTime> (); - foreach (var f in GetOutputFiles (configuration)) - fileTimes [f] = File.GetLastWriteTime (f); + DirectorySnapshot snapshot = null; + if (target == ProjectService.BuildTarget || target == ProjectService.CleanTarget) { + var outputName = GetOutputFileName (configuration); + if (!outputName.IsNullOrEmpty) { + snapshot = new DirectorySnapshot (outputName.ParentDirectory); + } + } try { var tr = await OnRunTarget (monitor, target, configuration, context); @@ -1158,130 +1161,169 @@ namespace MonoDevelop.Projects tr.BuildResult.SourceTarget = this; return tr; } finally { - // If any of the project generated files changes, notify it - foreach (var e in fileTimes) { - if (File.GetLastWriteTime (e.Key) != e.Value) - FileService.NotifyFileChanged (e.Key); + snapshot?.CheckChanges (); + } + } + + class DirectorySnapshot + { + FilePath filePath; + Dictionary<FilePath, DateTime> fileTimes = new Dictionary<FilePath, DateTime> (); + + public DirectorySnapshot (FilePath filePath) + { + this.filePath = filePath; + try { + if (Directory.Exists (filePath)) { + var files = Directory.GetFiles (filePath, "*", SearchOption.AllDirectories); + foreach (var f in files) { + fileTimes [f] = File.GetLastWriteTime (f); + } + } + } catch (Exception ex) { + LoggingService.LogError ("Error in file change monitoring", ex); + } + } + + internal void CheckChanges () + { + FileService.FreezeEvents (); + try { + var files = Directory.GetFiles (filePath, "*", SearchOption.AllDirectories); + foreach (var f in files) { + if (fileTimes.TryGetValue (f, out DateTime old)) { + fileTimes.Remove (f); + if (old != File.GetLastWriteTime (f)) { + FileService.NotifyFileChanged (f); + } + } + } + if (fileTimes.Count > 0) { + FileService.NotifyFilesRemoved (fileTimes.Keys); + } + } catch (Exception ex) { + LoggingService.LogError ("Error in file change monitoring", ex); + } finally { + FileService.ThawEvents (); } } } async Task<TargetEvaluationResult> RunMSBuildTarget (ProgressMonitor monitor, string target, ConfigurationSelector configuration, TargetEvaluationContext context) { - if (CheckUseMSBuildEngine (configuration)) { - var configs = GetConfigurations (configuration); + if (!CheckUseMSBuildEngine (configuration)) { + CleanupProjectBuilder (); + if (this is DotNetProject) { + var handler = new MonoDevelop.Projects.MD1.MD1DotNetProjectHandler ((DotNetProject)this); + return new TargetEvaluationResult (await handler.RunTarget (monitor, target, configuration)); + } + return null; + } - string [] evaluateItems = context != null ? context.ItemsToEvaluate.ToArray () : new string [0]; - string [] evaluateProperties = context != null ? context.PropertiesToEvaluate.ToArray () : new string [0]; + var configs = await GetConfigurations (configuration); - var globalProperties = CreateGlobalProperties (); - if (context != null) { - var md = (ProjectItemMetadata)context.GlobalProperties; - md.SetProject (sourceProject); - foreach (var p in md.GetProperties ()) - globalProperties [p.Name] = p.Value; - } + string [] evaluateItems = context != null ? context.ItemsToEvaluate.ToArray () : new string [0]; + string [] evaluateProperties = context != null ? context.PropertiesToEvaluate.ToArray () : new string [0]; - MSBuildResult result = null; - await Task.Run (async delegate { + var globalProperties = CreateGlobalProperties (); + if (context != null) { + var md = (ProjectItemMetadata)context.GlobalProperties; + md.SetProject (sourceProject); + foreach (var p in md.GetProperties ()) + globalProperties [p.Name] = p.Value; + } - bool operationRequiresExclusiveLock = false; - TimerCounter buildTimer = null; - switch (target) { - case "Build": buildTimer = Counters.BuildMSBuildProjectTimer; operationRequiresExclusiveLock = true; break; - case "Clean": buildTimer = Counters.CleanMSBuildProjectTimer; operationRequiresExclusiveLock = true; break; - } + MSBuildResult result = null; + await Task.Run (async delegate { - var t1 = Counters.RunMSBuildTargetTimer.BeginTiming (GetProjectEventMetadata (configuration)); - var t2 = buildTimer != null ? buildTimer.BeginTiming (GetProjectEventMetadata (configuration)) : null; + bool operationRequiresExclusiveLock = false; + TimerCounter buildTimer = null; + switch (target) { + case "Build": buildTimer = Counters.BuildMSBuildProjectTimer; operationRequiresExclusiveLock = true; break; + case "Clean": buildTimer = Counters.CleanMSBuildProjectTimer; operationRequiresExclusiveLock = true; break; + } - bool newBuilderRequested = false; + var t1 = Counters.RunMSBuildTargetTimer.BeginTiming (GetProjectEventMetadata (configuration)); + var t2 = buildTimer != null ? buildTimer.BeginTiming (GetProjectEventMetadata (configuration)) : null; - RemoteProjectBuilder builder = await GetProjectBuilder ().ConfigureAwait (false); + bool newBuilderRequested = false; - // If the builder requires an exclusive lock and it is busy, create a new locked builder. - // Fast operations that don't require an exclusive lock can use any builder, either locked or not + RemoteProjectBuilder builder = await GetProjectBuilder ().ConfigureAwait (false); - if (builder.IsBusy && operationRequiresExclusiveLock) { - builder.ReleaseReference (); - newBuilderRequested = true; - builder = await RequestLockedBuilder ().ConfigureAwait (false); - } - else - builder.Lock (); + // If the builder requires an exclusive lock and it is busy, create a new locked builder. + // Fast operations that don't require an exclusive lock can use any builder, either locked or not - string [] targets; - if (target.IndexOf (';') != -1) - targets = target.Split (new [] { ';' }, StringSplitOptions.RemoveEmptyEntries); - else - targets = new string [] { target }; - - try { - result = await builder.Run (configs, monitor.Log, new ProxyLogger (this, context.Loggers), context.LogVerbosity, targets, evaluateItems, evaluateProperties, globalProperties, monitor.CancellationToken).ConfigureAwait (false); - } finally { - builder.Unlock (); - builder.ReleaseReference (); - if (newBuilderRequested) { - // Dispose the builder after a while, so that it can be reused - #pragma warning disable 4014 - Task.Delay (10000).ContinueWith (t => builder.Dispose ()); - #pragma warning restore 4014 - } - t1.End (); - if (t2 != null) - t2.End (); - } - }); + if (builder.IsBusy && operationRequiresExclusiveLock) { + builder.ReleaseReference (); + newBuilderRequested = true; + builder = await RequestLockedBuilder ().ConfigureAwait (false); + } + else + builder.Lock (); + + string [] targets; + if (target.IndexOf (';') != -1) + targets = target.Split (new [] { ';' }, StringSplitOptions.RemoveEmptyEntries); + else + targets = new string [] { target }; - var br = new BuildResult (); - foreach (var err in result.Errors) { - FilePath file = null; - if (err.File != null) - file = Path.Combine (Path.GetDirectoryName (err.ProjectFile), err.File); - - br.Append (new BuildError (file, err.LineNumber, err.ColumnNumber, err.Code, err.Message) { - Subcategory = err.Subcategory, - EndLine = err.EndLineNumber, - EndColumn = err.EndColumnNumber, - IsWarning = err.IsWarning, - HelpKeyword = err.HelpKeyword, - }); - } - - // Get the evaluated properties - - var properties = new Dictionary<string, IMSBuildPropertyEvaluated> (); - foreach (var p in result.Properties) - properties [p.Key] = new MSBuildPropertyEvaluated (sourceProject, p.Key, p.Value, p.Value); - - var props = new MSBuildPropertyGroupEvaluated (sourceProject); - props.SetProperties (properties); - - // Get the evaluated items - - var evItems = new List<IMSBuildItemEvaluated> (); - foreach (var it in result.Items.SelectMany (d => d.Value)) { - var eit = new MSBuildItemEvaluated (sourceProject, it.Name, it.ItemSpec, it.ItemSpec); - if (it.Metadata.Count > 0) { - var imd = (MSBuildPropertyGroupEvaluated)eit.Metadata; - properties = new Dictionary<string, IMSBuildPropertyEvaluated> (); - foreach (var m in it.Metadata) - properties [m.Key] = new MSBuildPropertyEvaluated (sourceProject, m.Key, m.Value, m.Value); - imd.SetProperties (properties); + try { + result = await builder.Run (configs, monitor.Log, new ProxyLogger (this, context.Loggers), context.LogVerbosity, targets, evaluateItems, evaluateProperties, globalProperties, monitor.CancellationToken).ConfigureAwait (false); + } finally { + builder.Unlock (); + builder.ReleaseReference (); + if (newBuilderRequested) { + // Dispose the builder after a while, so that it can be reused + #pragma warning disable 4014 + Task.Delay (10000).ContinueWith (t => builder.Dispose ()); + #pragma warning restore 4014 } - evItems.Add (eit); + t1.End (); + if (t2 != null) + t2.End (); } + }); - return new TargetEvaluationResult (br, evItems, props); + var br = new BuildResult (); + foreach (var err in result.Errors) { + FilePath file = null; + if (err.File != null) + file = Path.Combine (Path.GetDirectoryName (err.ProjectFile), err.File); + + br.Append (new BuildError (file, err.LineNumber, err.ColumnNumber, err.Code, err.Message) { + Subcategory = err.Subcategory, + EndLine = err.EndLineNumber, + EndColumn = err.EndColumnNumber, + IsWarning = err.IsWarning, + HelpKeyword = err.HelpKeyword, + }); } - else { - CleanupProjectBuilder (); - if (this is DotNetProject) { - var handler = new MonoDevelop.Projects.MD1.MD1DotNetProjectHandler ((DotNetProject)this); - return new TargetEvaluationResult (await handler.RunTarget (monitor, target, configuration)); + + // Get the evaluated properties + + var properties = new Dictionary<string, IMSBuildPropertyEvaluated> (); + foreach (var p in result.Properties) + properties [p.Key] = new MSBuildPropertyEvaluated (sourceProject, p.Key, p.Value, p.Value); + + var props = new MSBuildPropertyGroupEvaluated (sourceProject); + props.SetProperties (properties); + + // Get the evaluated items + + var evItems = new List<IMSBuildItemEvaluated> (); + foreach (var it in result.Items.SelectMany (d => d.Value)) { + var eit = new MSBuildItemEvaluated (sourceProject, it.Name, it.ItemSpec, it.ItemSpec); + if (it.Metadata.Count > 0) { + var imd = (MSBuildPropertyGroupEvaluated)eit.Metadata; + properties = new Dictionary<string, IMSBuildPropertyEvaluated> (); + foreach (var m in it.Metadata) + properties [m.Key] = new MSBuildPropertyEvaluated (sourceProject, m.Key, m.Value, m.Value); + imd.SetProperties (properties); } + evItems.Add (eit); } - return null; + + return new TargetEvaluationResult (br, evItems, props); } string activeTargetFramework; @@ -1341,14 +1383,14 @@ namespace MonoDevelop.Projects return properties; } - internal ProjectConfigurationInfo [] GetConfigurations (ConfigurationSelector configuration, bool includeReferencedProjects = true) + internal Task<ProjectConfigurationInfo[]> GetConfigurations (ConfigurationSelector configuration, bool includeReferencedProjects = true, CancellationToken token = default(CancellationToken)) { var visitedProjects = new HashSet<Project> (); visitedProjects.Add (this); - return GetConfigurations (configuration, includeReferencedProjects, visitedProjects); + return GetConfigurations (configuration, includeReferencedProjects, visitedProjects, token); } - ProjectConfigurationInfo[] GetConfigurations (ConfigurationSelector configuration, bool includeReferencedProjects, HashSet<Project> visited) + async Task<ProjectConfigurationInfo[]> GetConfigurations (ConfigurationSelector configuration, bool includeReferencedProjects, HashSet<Project> visited, CancellationToken token) { var sc = ParentSolution != null ? ParentSolution.GetConfiguration (configuration) : null; @@ -1363,12 +1405,13 @@ namespace MonoDevelop.Projects Enabled = sc == null || sc.BuildEnabledForItem (this) }); if (includeReferencedProjects) { - foreach (var refProject in GetReferencedItems (configuration).OfType<Project> ().Where (p => p.SupportsBuild ())) { + var refedItems = await GetReferencedItems (configuration, token); + foreach (var refProject in refedItems.OfType<Project> ().Where (p => p.SupportsBuild ())) { if (!visited.Add (refProject)) continue; // Recursively get all referenced projects. This is necessary if one of the referenced // projects is using the local copy flag. - foreach (var rp in refProject.GetConfigurations (configuration, true, visited)) { + foreach (var rp in await refProject.GetConfigurations (configuration, true, visited, token)) { if (!configs.Any (pc => pc.ProjectFile == rp.ProjectFile)) configs.Add (rp); } @@ -1415,7 +1458,7 @@ namespace MonoDevelop.Projects projectBuilder.Shutdown (); projectBuilder.ReleaseReference (); } - var pb = await MSBuildProjectService.GetProjectBuilder (runtime, ToolsVersion, FileName, slnFile, 0, RequiresMicrosoftBuild); + var pb = await MSBuildProjectService.GetProjectBuilder (runtime, ToolsVersion, FileName, slnFile, 0, true); pb.AddReference (); pb.Disconnected += delegate { CleanupProjectBuilder (); @@ -1457,8 +1500,8 @@ namespace MonoDevelop.Projects return; // Check project references. - foreach (var projectReference in dotNetProject.References.Where (pr => pr.ReferenceType == ReferenceType.Project)) {
- if (traversedProjects.Contains (projectReference.ProjectGuid))
+ foreach (var projectReference in dotNetProject.References.Where (pr => pr.ReferenceType == ReferenceType.Project)) { + if (traversedProjects.Contains (projectReference.ProjectGuid)) continue; var p = projectReference.ResolveProject (ParentSolution); @@ -1484,7 +1527,7 @@ namespace MonoDevelop.Projects var sln = ParentSolution; var slnFile = sln != null ? sln.FileName : null; - var pb = await MSBuildProjectService.GetProjectBuilder (runtime, ToolsVersion, FileName, slnFile, 0, RequiresMicrosoftBuild, true); + var pb = await MSBuildProjectService.GetProjectBuilder (runtime, ToolsVersion, FileName, slnFile, 0, true); pb.AddReference (); if (modifiedInMemory) { try { @@ -1523,7 +1566,7 @@ namespace MonoDevelop.Projects #endregion /// <summary>Whether to use the MSBuild engine for the specified item.</summary> - internal bool CheckUseMSBuildEngine (ConfigurationSelector sel, bool checkReferences = true) + internal bool CheckUseMSBuildEngine (ConfigurationSelector sel) { return !MSBuildEngineSupport.HasFlag (MSBuildSupport.NotSupported); } @@ -1653,6 +1696,20 @@ namespace MonoDevelop.Projects async Task<TargetEvaluationResult> RunBuildTarget (ProgressMonitor monitor, ConfigurationSelector configuration, TargetEvaluationContext context) { + if (UsingMSBuildEngine (configuration)) { + var result = await RunMSBuildTarget (monitor, "Build", configuration, context); + if (!result.BuildResult.Failed) + SetFastBuildCheckClean (configuration); + return result; + } +#pragma warning disable 618 + return await RunDeprecatedBuild (monitor, configuration, context); +#pragma warning restore 618 + } + + [Obsolete] + async Task<TargetEvaluationResult> RunDeprecatedBuild (ProgressMonitor monitor, ConfigurationSelector configuration, TargetEvaluationContext context) + { // create output directory, if not exists ProjectConfiguration conf = GetConfiguration (configuration) as ProjectConfiguration; if (conf == null) { @@ -1660,16 +1717,9 @@ namespace MonoDevelop.Projects cres.AddError (GettextCatalog.GetString ("Configuration '{0}' not found in project '{1}'", configuration.ToString (), Name)); return new TargetEvaluationResult (cres); } - - StringParserService.Properties["Project"] = Name; - - if (UsingMSBuildEngine (configuration)) { - var result = await RunMSBuildTarget (monitor, "Build", configuration, context); - if (!result.BuildResult.Failed) - SetFastBuildCheckClean (configuration); - return result; - } - + + StringParserService.Properties ["Project"] = Name; + string outputDir = conf.OutputDirectory; try { DirectoryInfo directoryInfo = new DirectoryInfo (outputDir); @@ -1682,9 +1732,9 @@ namespace MonoDevelop.Projects //copy references and files marked to "CopyToOutputDirectory" CopySupportFiles (monitor, configuration); - + monitor.Log.WriteLine (GettextCatalog.GetString ("Performing main compilation…")); - + BuildResult res = await DoBuild (monitor, configuration); if (res != null) { @@ -1695,6 +1745,7 @@ namespace MonoDevelop.Projects } return new TargetEvaluationResult (res); + } bool disableFastUpToDateCheck; @@ -1704,24 +1755,45 @@ namespace MonoDevelop.Projects string fastUpToDateCheckGoodConfig; DateTime fastUpToDateTimestamp; + [Obsolete ("Use the overload that returns a task")] public bool FastCheckNeedsBuild (ConfigurationSelector configuration) { - return ProjectExtension.OnFastCheckNeedsBuild (configuration); + return FastCheckNeedsBuild (configuration, CancellationToken.None).Result; } - + + public Task<bool> FastCheckNeedsBuild (ConfigurationSelector configuration, CancellationToken token) + { + return ProjectExtension.OnFastCheckNeedsBuild (configuration, token); + } + + [Obsolete("Use the overload that returns a task")] protected virtual bool OnFastCheckNeedsBuild (ConfigurationSelector configuration) { + return false; + } + + protected virtual async Task<bool> OnFastCheckNeedsBuild (ConfigurationSelector configuration, CancellationToken token) + { if (disableFastUpToDateCheck || fastUpToDateCheckGoodConfig == null) return true; + var cfg = GetConfiguration (configuration); if (cfg == null || cfg.Id != fastUpToDateCheckGoodConfig) return true; + //chain to the obsoleted version +#pragma warning disable 618 + if (ProjectExtension.OnFastCheckNeedsBuild (configuration)) { + return true; + } +#pragma warning restore 618 + // Shouldn't need to build, but if a dependency was changed since this project build flag was reset, // the project needs to be rebuilt - foreach (var dep in GetReferencedItems (configuration).OfType<Project> ()) { - if (dep.FastCheckNeedsBuild (configuration) || dep.fastUpToDateTimestamp >= fastUpToDateTimestamp) { + var items = await GetReferencedItems (configuration, token); + foreach (var dep in items.OfType<Project> ()) { + if (await dep.FastCheckNeedsBuild (configuration, token) || dep.fastUpToDateTimestamp >= fastUpToDateTimestamp) { fastUpToDateCheckGoodConfig = null; return true; } @@ -1741,19 +1813,7 @@ namespace MonoDevelop.Projects fastUpToDateTimestamp = DateTime.Now; } - /// <summary> - /// Copies the support files to the output directory - /// </summary> - /// <param name='monitor'> - /// Progress monitor. - /// </param> - /// <param name='configuration'> - /// Configuration for which to copy the files. - /// </param> - /// <remarks> - /// Copies all support files to the output directory of the given configuration. Support files - /// include: assembly references with the Local Copy flag, data files with the Copy to Output option, etc. - /// </remarks> + [Obsolete("Use MSBuild")] public void CopySupportFiles (ProgressMonitor monitor, ConfigurationSelector configuration) { ProjectConfiguration config = (ProjectConfiguration) GetConfiguration (configuration); @@ -1792,19 +1852,7 @@ namespace MonoDevelop.Projects } } - /// <summary> - /// Removes all support files from the output directory - /// </summary> - /// <param name='monitor'> - /// Progress monitor. - /// </param> - /// <param name='configuration'> - /// Configuration for which to delete the files. - /// </param> - /// <remarks> - /// Deletes all support files from the output directory of the given configuration. Support files - /// include: assembly references with the Local Copy flag, data files with the Copy to Output option, etc. - /// </remarks> + [Obsolete ("Use MSBuild")] public async Task DeleteSupportFiles (ProgressMonitor monitor, ConfigurationSelector configuration) { ProjectConfiguration config = (ProjectConfiguration) GetConfiguration (configuration); @@ -1837,6 +1885,7 @@ namespace MonoDevelop.Projects /// Returns a list of all files that are required to use the project output binary, for example: data files with /// the Copy to Output option, debug information files, generated resource files, etc. /// </remarks> + [Obsolete ("Use MSBuild")] public FileCopySet GetSupportFileList (ConfigurationSelector configuration) { var list = new FileCopySet (); @@ -1844,19 +1893,7 @@ namespace MonoDevelop.Projects return list; } - /// <summary> - /// Gets a list of files required to use the project output - /// </summary> - /// <param name='list'> - /// List where to add the support files. - /// </param> - /// <param name='configuration'> - /// Build configuration for which get the list - /// </param> - /// <remarks> - /// Returns a list of all files that are required to use the project output binary, for example: data files with - /// the Copy to Output option, debug information files, generated resource files, etc. - /// </remarks> + [Obsolete ("Use MSBuild")] internal protected virtual void PopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration) { ProjectExtension.OnPopulateSupportFileList (list, configuration); @@ -1870,19 +1907,7 @@ namespace MonoDevelop.Projects } } - /// <summary> - /// Gets a list of files generated when building this project - /// </summary> - /// <returns> - /// A list of files. - /// </returns> - /// <param name='configuration'> - /// Build configuration for which get the list - /// </param> - /// <remarks> - /// Returns a list of all files that are generated when this project is built, including: the generated binary, - /// debug information files, satellite assemblies. - /// </remarks> + [Obsolete ("Use MSBuild")] public List<FilePath> GetOutputFiles (ConfigurationSelector configuration) { if (configuration == null) { @@ -1893,19 +1918,7 @@ namespace MonoDevelop.Projects return list; } - /// <summary> - /// Gets a list of files retuired to use the project output - /// </summary> - /// <param name='list'> - /// List where to add the support files. - /// </param> - /// <param name='configuration'> - /// Build configuration for which get the list - /// </param> - /// <remarks> - /// Returns a list of all files that are required to use the project output binary, for example: data files with - /// the Copy to Output option, debug information files, generated resource files, etc. - /// </remarks> + [Obsolete ("Use MSBuild")] internal protected virtual void PopulateOutputFileList (List<FilePath> list, ConfigurationSelector configuration) { ProjectExtension.OnPopulateOutputFileList (list, configuration); @@ -1940,22 +1953,7 @@ namespace MonoDevelop.Projects return base.Build (monitor, solutionConfiguration, buildReferences, operationContext); } - /// <summary> - /// Builds the project. - /// </summary> - /// <returns> - /// The build result. - /// </returns> - /// <param name='monitor'> - /// Progress monitor. - /// </param> - /// <param name='configuration'> - /// Configuration to build. - /// </param> - /// <remarks> - /// This method is invoked to build the project. Support files such as files with the Copy to Output flag will - /// be copied before calling this method. - /// </remarks> + [Obsolete("Use MSBuild")] protected virtual Task<BuildResult> DoBuild (ProgressMonitor monitor, ConfigurationSelector configuration) { return Task.FromResult (BuildResult.CreateSuccess ()); @@ -1966,18 +1964,25 @@ namespace MonoDevelop.Projects return (await RunTarget (monitor, "Clean", configuration, new TargetEvaluationContext (operationContext))).BuildResult; } - async Task<TargetEvaluationResult> RunCleanTarget (ProgressMonitor monitor, ConfigurationSelector configuration, TargetEvaluationContext context) + Task<TargetEvaluationResult> RunCleanTarget (ProgressMonitor monitor, ConfigurationSelector configuration, TargetEvaluationContext context) + { + if (UsingMSBuildEngine (configuration)) { + return RunMSBuildTarget (monitor, "Clean", configuration, context); + } +#pragma warning disable 618 + return RunDeprecatedClean (monitor, configuration, context); +#pragma warning restore 618 + } + + [Obsolete] + async Task<TargetEvaluationResult> RunDeprecatedClean (ProgressMonitor monitor, ConfigurationSelector configuration, TargetEvaluationContext context) { ProjectConfiguration config = GetConfiguration (configuration) as ProjectConfiguration; if (config == null) { monitor.ReportError (GettextCatalog.GetString ("Configuration '{0}' not found in project '{1}'", configuration, Name), null); return new TargetEvaluationResult (BuildResult.CreateSuccess ()); } - - if (UsingMSBuildEngine (configuration)) { - return await RunMSBuildTarget (monitor, "Clean", configuration, context); - } - + monitor.Log.WriteLine ("Removing output files..."); var filesToDelete = GetOutputFiles (configuration).ToArray (); @@ -2000,6 +2005,7 @@ namespace MonoDevelop.Projects return new TargetEvaluationResult (res); } + [Obsolete ("Use MSBuild")] protected virtual Task<BuildResult> DoClean (ProgressMonitor monitor, ConfigurationSelector configuration) { return Task.FromResult (BuildResult.CreateSuccess ()); @@ -2032,27 +2038,7 @@ namespace MonoDevelop.Projects return FilePath.Null; } - internal protected override bool OnGetNeedsBuilding (ConfigurationSelector configuration) - { - return CheckNeedsBuild (configuration); - } - - protected override void OnSetNeedsBuilding (ConfigurationSelector configuration) - { - var of = GetOutputFileName (configuration); - if (File.Exists (of)) - File.Delete (of); - } - - /// <summary> - /// Checks if the project needs to be built - /// </summary> - /// <returns> - /// <c>True</c> if the project needs to be built (it has changes) - /// </returns> - /// <param name='configuration'> - /// Build configuration. - /// </param> + [Obsolete ("Use FastCheckNeedsBuild")] protected virtual bool CheckNeedsBuild (ConfigurationSelector configuration) { DateTime tim = GetLastBuildTime (configuration); @@ -2085,6 +2071,7 @@ namespace MonoDevelop.Projects return false; } + [Obsolete] protected internal override DateTime OnGetLastBuildTime (ConfigurationSelector configuration) { string file = GetOutputFileName (configuration); @@ -3868,11 +3855,13 @@ namespace MonoDevelop.Projects return Project.OnCreateProjectItem (item); } + [Obsolete("Use MSBuild")] internal protected override void OnPopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration) { Project.DoPopulateSupportFileList (list, configuration); } + [Obsolete("UseMSBuild")] internal protected override void OnPopulateOutputFileList (List<FilePath> list, ConfigurationSelector configuration) { Project.DoPopulateOutputFileList (list, configuration); @@ -3954,11 +3943,6 @@ namespace MonoDevelop.Projects Project.OnPrepareForEvaluation (project); } - internal protected override bool OnFastCheckNeedsBuild (ConfigurationSelector configuration) - { - return Project.OnFastCheckNeedsBuild (configuration); - } - internal protected override Task<ProjectFile []> OnGetSourceFiles (ProgressMonitor monitor, ConfigurationSelector configuration) { return Project.OnGetSourceFiles (monitor, configuration); @@ -3978,6 +3962,17 @@ namespace MonoDevelop.Projects { Project.OnItemsRemoved (objs); } + + [Obsolete] + internal protected override bool OnFastCheckNeedsBuild (ConfigurationSelector configuration) + { + return Project.OnFastCheckNeedsBuild (configuration); + } + + internal protected override Task<bool> OnFastCheckNeedsBuild (ConfigurationSelector configuration, CancellationToken token) + { + return Project.OnFastCheckNeedsBuild (configuration, token); + } } } diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectExtension.cs index 5d32a28e6a..0f91715879 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectExtension.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectExtension.cs @@ -1,4 +1,4 @@ -// +// // MSBuildProjectExtension.cs // // Author: @@ -31,6 +31,7 @@ using MonoDevelop.Projects.MSBuild; using Mono.Addins; using System.Linq; using System.Collections.Immutable; +using System.Threading; namespace MonoDevelop.Projects { @@ -197,11 +198,13 @@ namespace MonoDevelop.Projects return next.OnCreateProjectItem (item); } + [Obsolete("Use MSBuild")] internal protected virtual void OnPopulateSupportFileList (FileCopySet list, ConfigurationSelector configuration) { next.OnPopulateSupportFileList (list, configuration); } + [Obsolete("Use MSBuild")] internal protected virtual void OnPopulateOutputFileList (List<FilePath> list, ConfigurationSelector configuration) { next.OnPopulateOutputFileList (list, configuration); @@ -218,11 +221,17 @@ namespace MonoDevelop.Projects } } + [Obsolete("Use the overload the returns a Task")] internal protected virtual bool OnFastCheckNeedsBuild (ConfigurationSelector configuration) { return next.OnFastCheckNeedsBuild (configuration); } + internal protected virtual Task<bool> OnFastCheckNeedsBuild (ConfigurationSelector configuration, CancellationToken token) + { + return next.OnFastCheckNeedsBuild (configuration, token); + } + #endregion #region Events diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs index 7aa8e22ca5..7a14cc8d4b 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs @@ -438,11 +438,13 @@ namespace MonoDevelop.Projects return GetAllItems<Project> ().Select (p => p.GetFlavor<T> ()).Where (p => p != null); } + [Obsolete ("This method will be removed in future releases")] public ReadOnlyCollection<T> GetAllSolutionItemsWithTopologicalSort<T> (ConfigurationSelector configuration) where T: SolutionItem { return RootFolder.GetAllItemsWithTopologicalSort<T> (configuration); } - + + [Obsolete ("This method will be removed in future releases")] public ReadOnlyCollection<Project> GetAllProjectsWithTopologicalSort (ConfigurationSelector configuration) { return RootFolder.GetAllProjectsWithTopologicalSort (configuration); @@ -670,6 +672,7 @@ namespace MonoDevelop.Projects return SolutionExtension.Build (monitor, configuration, operationContext); } + [Obsolete ("This method will be removed in future releases")] public bool NeedsBuilding (ConfigurationSelector configuration) { return SolutionExtension.NeedsBuilding (configuration); @@ -807,7 +810,9 @@ namespace MonoDevelop.Projects return RootFolder.Build (monitor, configuration, operationContext:operationContext); } - /*protected virtual*/ bool OnGetNeedsBuilding (ConfigurationSelector configuration) + [Obsolete ("This method will be removed in future releases")] + /*protected virtual*/ + bool OnGetNeedsBuilding (ConfigurationSelector configuration) { return RootFolder.NeedsBuilding (configuration); } @@ -1230,6 +1235,7 @@ namespace MonoDevelop.Projects return Solution.OnBuild (monitor, configuration, operationContext); } + [Obsolete ("This method will be removed in future releases")] internal protected override bool NeedsBuilding (ConfigurationSelector configuration) { return Solution.OnGetNeedsBuilding (configuration); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionExtension.cs index a6dfcb7615..cd98d83f9a 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionExtension.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionExtension.cs @@ -118,6 +118,7 @@ namespace MonoDevelop.Projects return next.OnGetRunConfigurations (); } + [Obsolete ("This method will be removed in future releases")] internal protected virtual bool NeedsBuilding (ConfigurationSelector configuration) { return next.NeedsBuilding (configuration); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs index 9793cc5f99..23de03091d 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolder.cs @@ -39,6 +39,7 @@ using MonoDevelop.Projects.Extensions; using MonoDevelop.Core.Serialization; using System.Threading.Tasks; using System.Collections.Immutable; +using System.Threading; namespace MonoDevelop.Projects { @@ -419,7 +420,8 @@ namespace MonoDevelop.Projects { return GetAllItems<SolutionFolderItem> (); } - + + [Obsolete ("This method will be removed in future releases")] public ReadOnlyCollection<T> GetAllItemsWithTopologicalSort<T> (ConfigurationSelector configuration) where T: SolutionItem { List<T> list = new List<T> (); @@ -433,9 +435,10 @@ namespace MonoDevelop.Projects GetAllItems<Project> (list, this); return list.AsReadOnly (); } - + // The projects are returned in the order // they should be compiled, acording to their references. + [Obsolete ("This method will be removed in future releases")] public ReadOnlyCollection<Project> GetAllProjectsWithTopologicalSort (ConfigurationSelector configuration) { List<Project> list = new List<Project> (); @@ -454,23 +457,41 @@ namespace MonoDevelop.Projects GetAllItems<T> (list, ce); } } - + + [Obsolete("Use the overload that returns a Task")] + public ReadOnlyCollection<SolutionItem> GetAllBuildableEntries (ConfigurationSelector configuration) + { + return GetAllBuildableEntries (configuration, false, false); + } + + [Obsolete ("Use the overload that returns a Task")] public ReadOnlyCollection<SolutionItem> GetAllBuildableEntries (ConfigurationSelector configuration, bool topologicalSort, bool includeExternalReferences) { + return GetAllBuildableEntries (configuration, topologicalSort, includeExternalReferences, CancellationToken.None).Result; + } + + public Task<ReadOnlyCollection<SolutionItem>> GetAllBuildableEntries (ConfigurationSelector configuration, CancellationToken token) + { + return GetAllBuildableEntries (configuration, false, false, token); + } + + public async Task<ReadOnlyCollection<SolutionItem>> GetAllBuildableEntries ( + ConfigurationSelector configuration, + bool topologicalSort, + bool includeExternalReferences, + CancellationToken token) + { var list = new List<SolutionItem> (); - GetAllBuildableEntries (list, configuration, includeExternalReferences); + await GetAllBuildableEntries (list, configuration, includeExternalReferences, token); if (topologicalSort) - return SolutionItem.TopologicalSort<SolutionItem> (list, configuration); + return await SolutionItem.TopologicalSort (list, configuration, token); else return list.AsReadOnly (); } - - public ReadOnlyCollection<SolutionItem> GetAllBuildableEntries (ConfigurationSelector configuration) - { - return GetAllBuildableEntries (configuration, false, false); - } - - void GetAllBuildableEntries (List<SolutionItem> list, ConfigurationSelector configuration, bool includeExternalReferences) + + async Task GetAllBuildableEntries ( + List<SolutionItem> list, ConfigurationSelector configuration, + bool includeExternalReferences, CancellationToken token) { if (ParentSolution == null) return; @@ -480,13 +501,15 @@ namespace MonoDevelop.Projects foreach (SolutionFolderItem item in Items) { if (item is SolutionFolder) - ((SolutionFolder)item).GetAllBuildableEntries (list, configuration, includeExternalReferences); + await ((SolutionFolder)item).GetAllBuildableEntries (list, configuration, includeExternalReferences, token); else if ((item is SolutionItem) && conf.BuildEnabledForItem ((SolutionItem) item) && ((SolutionItem)item).SupportsBuild ()) - GetAllBuildableReferences (list, (SolutionItem)item, configuration, conf, includeExternalReferences, false); + await GetAllBuildableReferences (list, (SolutionItem)item, configuration, conf, includeExternalReferences, false, token); } } - void GetAllBuildableReferences (List<SolutionItem> list, SolutionItem item, ConfigurationSelector configuration, SolutionConfiguration conf, bool includeExternalReferences, bool isDirectReference) + async Task GetAllBuildableReferences ( + List<SolutionItem> list, SolutionItem item, ConfigurationSelector configuration, + SolutionConfiguration conf, bool includeExternalReferences, bool isDirectReference, CancellationToken token) { if (list.Contains (item) || !conf.BuildEnabledForItem (item)) return; @@ -495,8 +518,8 @@ namespace MonoDevelop.Projects return; list.Add (item); if (includeExternalReferences) { - foreach (var it in item.GetReferencedItems (configuration)) - GetAllBuildableReferences (list, it, configuration, conf, includeExternalReferences, true); + foreach (var it in await item.GetReferencedItems (configuration, token)) + await GetAllBuildableReferences (list, it, configuration, conf, includeExternalReferences, true, token); } } @@ -586,7 +609,7 @@ namespace MonoDevelop.Projects ReadOnlyCollection<SolutionItem> allProjects; try { - allProjects = GetAllBuildableEntries (configuration, true, true); + allProjects = await GetAllBuildableEntries (configuration, true, true, monitor.CancellationToken); } catch (CyclicDependencyException) { monitor.ReportError (GettextCatalog.GetString ("Cyclic dependencies are not supported."), null); return new BuildResult ("", 1, 1); @@ -615,7 +638,7 @@ namespace MonoDevelop.Projects ReadOnlyCollection<SolutionItem> allProjects; try { - allProjects = GetAllBuildableEntries (configuration, true, true); + allProjects = await GetAllBuildableEntries (configuration, true, true, monitor.CancellationToken); } catch (CyclicDependencyException) { monitor.ReportError (GettextCatalog.GetString ("Cyclic dependencies are not supported."), null); return new BuildResult ("", 1, 1); @@ -664,7 +687,8 @@ namespace MonoDevelop.Projects // Get a list of the status objects for all items on which this one depends - var refStatus = item.GetReferencedItems (configuration).Select (it => { + var refItems = await item.GetReferencedItems (configuration, monitor.CancellationToken); + var refStatus = refItems.Select (it => { BuildStatus bs; buildStatus.TryGetValue (it, out bs); return bs; @@ -704,11 +728,13 @@ namespace MonoDevelop.Projects return cres; } + [Obsolete ("This method will be removed in future releases")] public bool NeedsBuilding (ConfigurationSelector configuration) { - return Items.OfType<IBuildTarget>().Any (t => t.NeedsBuilding (configuration)); + return true; } + [Obsolete ("This method will be removed in future releases")] protected internal override DateTime OnGetLastBuildTime (ConfigurationSelector configuration) { // Return the min value, since that the last time all items in the diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItem.cs index 58eb5625b2..ec931a6667 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItem.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionFolderItem.cs @@ -339,6 +339,7 @@ namespace MonoDevelop.Projects /// <param name='configuration'> /// Configuration for which to get the last build time. /// </param> + [Obsolete("Use MSBuild")] public DateTime GetLastBuildTime (ConfigurationSelector configuration) { return OnGetLastBuildTime (configuration); @@ -486,6 +487,7 @@ namespace MonoDevelop.Projects /// <param name='configuration'> /// Configuration for which to get the last build time. /// </param> + [Obsolete] internal protected virtual DateTime OnGetLastBuildTime (ConfigurationSelector configuration) { return DateTime.MinValue; diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs index c3743e6ad5..b065d5cf55 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs @@ -49,6 +49,7 @@ using MonoDevelop.Core.Collections; using System.Threading.Tasks; using MonoDevelop.Projects.MSBuild; using System.Collections.Immutable; +using System.Threading; namespace MonoDevelop.Projects { @@ -370,12 +371,19 @@ namespace MonoDevelop.Projects /// <param name='configuration'> /// Configuration for which to get the referenced items /// </param> + public Task<List<SolutionItem>> GetReferencedItems (ConfigurationSelector configuration, CancellationToken token) + { + return ItemExtension.OnGetReferencedItems (configuration, token); + } + + [Obsolete ("Use the overload that returns a Task")] public IEnumerable<SolutionItem> GetReferencedItems (ConfigurationSelector configuration) { - return ItemExtension.OnGetReferencedItems (configuration); + return GetReferencedItems (configuration, CancellationToken.None).Result; } - public IEnumerable<T> GetReferencedExtensionsFromFlavor<T> (string projectTypeName, ConfigurationSelector configuration) where T : ProjectExtension + [Obsolete("This is extension-specific functionality that should not be in core")] + public IEnumerable<T> GetReferencedExtensionsFromFlavor<T> (string projectTypeName, ConfigurationSelector configuration) where T : ProjectExtension { var extensions = new List<T> (); var projects = ParentSolution.GetAllProjects (); @@ -393,11 +401,19 @@ namespace MonoDevelop.Projects return extensions; } + [Obsolete("Use the overload that returns a Task")] protected virtual IEnumerable<SolutionItem> OnGetReferencedItems (ConfigurationSelector configuration) { return dependencies; } + protected virtual Task<List<SolutionItem>> OnGetReferencedItems (ConfigurationSelector configuration, CancellationToken token) + { +#pragma warning disable 618 + return Task.FromResult (ItemExtension.OnGetReferencedItems (configuration).ToList ()); +#pragma warning restore 618 + } + /// <summary> /// Initializes a new instance of this item, using an xml element as template /// </summary> @@ -543,6 +559,7 @@ namespace MonoDevelop.Projects return ItemExtension.OnNeedsBuilding (configuration); } + [Obsolete ("This method will be removed in future releases")] internal protected virtual bool OnGetNeedsBuilding (ConfigurationSelector configuration) { return false; @@ -554,6 +571,7 @@ namespace MonoDevelop.Projects OnSetNeedsBuilding (configuration); } + [Obsolete ("This method will be removed in future releases")] protected virtual void OnSetNeedsBuilding (ConfigurationSelector configuration) { } @@ -618,9 +636,9 @@ namespace MonoDevelop.Projects var referenced = new List<SolutionItem> (); var visited = new Set<SolutionItem> (); - GetBuildableReferencedItems (visited, referenced, this, solutionConfiguration); + await GetBuildableReferencedItems (visited, referenced, this, solutionConfiguration, monitor.CancellationToken); - var sortedReferenced = TopologicalSort (referenced, solutionConfiguration); + var sortedReferenced = await TopologicalSort (referenced, solutionConfiguration, monitor.CancellationToken); SolutionItemConfiguration iconf = GetConfiguration (solutionConfiguration); string confName = iconf != null ? iconf.Id : solutionConfiguration.ToString (); @@ -683,23 +701,15 @@ namespace MonoDevelop.Projects return Task.FromResult (BuildResult.CreateSuccess ()); } - void GetBuildableReferencedItems (Set<SolutionItem> visited, List<SolutionItem> referenced, SolutionItem item, ConfigurationSelector configuration) + async Task GetBuildableReferencedItems (Set<SolutionItem> visited, List<SolutionItem> referenced, SolutionItem item, ConfigurationSelector configuration, CancellationToken token) { if (!visited.Add(item)) return; referenced.Add (item); - foreach (var ritem in item.GetReferencedItems (configuration)) - GetBuildableReferencedItems (visited, referenced, ritem, configuration); - } - - internal bool ContainsReferences (HashSet<SolutionItem> items, ConfigurationSelector conf) - { - foreach (var it in GetReferencedItems (conf)) - if (items.Contains (it)) - return true; - return false; + foreach (var ritem in await item.GetReferencedItems (configuration, token)) + await GetBuildableReferencedItems (visited, referenced, ritem, configuration, token); } /// <summary> @@ -776,6 +786,12 @@ namespace MonoDevelop.Projects return Task.FromResult (BuildResult.CreateSuccess ()); } + [Obsolete ("This method will be removed in future releases")] + public static ReadOnlyCollection<T> TopologicalSort<T> (IEnumerable<T> items, ConfigurationSelector configuration) where T : SolutionItem + { + return TopologicalSort (items, configuration, CancellationToken.None).Result; + } + /// <summary> /// Sorts a collection of solution items, taking into account the dependencies between them /// </summary> @@ -792,7 +808,7 @@ namespace MonoDevelop.Projects /// This methods sorts a collection of items, ensuring that every item is placed after all the items /// on which it depends. /// </remarks> - public static ReadOnlyCollection<T> TopologicalSort<T> (IEnumerable<T> items, ConfigurationSelector configuration) where T: SolutionItem + internal static async Task<ReadOnlyCollection<T>> TopologicalSort<T> (IEnumerable<T> items, ConfigurationSelector configuration, CancellationToken token) where T: SolutionItem { IList<T> allItems; allItems = items as IList<T>; @@ -804,12 +820,12 @@ namespace MonoDevelop.Projects bool[] triedToInsert = new bool[allItems.Count]; for (int i = 0; i < allItems.Count; ++i) { if (!inserted[i]) - Insert<T> (i, allItems, sortedEntries, inserted, triedToInsert, configuration); + await Insert (i, allItems, sortedEntries, inserted, triedToInsert, configuration, token); } return sortedEntries.AsReadOnly (); } - static void Insert<T> (int index, IList<T> allItems, List<T> sortedItems, bool[] inserted, bool[] triedToInsert, ConfigurationSelector solutionConfiguration) where T: SolutionItem + static async Task Insert<T> (int index, IList<T> allItems, List<T> sortedItems, bool[] inserted, bool[] triedToInsert, ConfigurationSelector solutionConfiguration, CancellationToken token) where T: SolutionItem { if (triedToInsert[index]) { throw new CyclicDependencyException (); @@ -817,12 +833,12 @@ namespace MonoDevelop.Projects triedToInsert[index] = true; var insertItem = allItems[index]; - foreach (var reference in insertItem.GetReferencedItems (solutionConfiguration)) { + foreach (var reference in await insertItem.GetReferencedItems (solutionConfiguration, token)) { for (int j=0; j < allItems.Count; ++j) { SolutionFolderItem checkItem = allItems[j]; if (reference == checkItem) { if (!inserted[j]) - Insert (j, allItems, sortedItems, inserted, triedToInsert, solutionConfiguration); + await Insert (j, allItems, sortedItems, inserted, triedToInsert, solutionConfiguration, token); break; } } @@ -1379,16 +1395,6 @@ namespace MonoDevelop.Projects return source; } - internal protected override DateTime OnGetLastBuildTime (ConfigurationSelector configuration) - { - return ItemExtension.OnGetLastBuildTime (configuration); - } - - DateTime DoGetLastBuildTime (ConfigurationSelector configuration) - { - return base.OnGetLastBuildTime (configuration); - } - protected virtual void OnDefaultConfigurationChanged (ConfigurationEventArgs args) { ItemExtension.OnDefaultConfigurationChanged (args); @@ -1511,11 +1517,17 @@ namespace MonoDevelop.Projects return Item.OnGetExecutionDependencies (); } + [Obsolete("Use the overload that returns a Task")] internal protected override IEnumerable<SolutionItem> OnGetReferencedItems (ConfigurationSelector configuration) { return Item.OnGetReferencedItems (configuration); } + internal protected override Task<List<SolutionItem>> OnGetReferencedItems (ConfigurationSelector configuration, CancellationToken token) + { + return Item.OnGetReferencedItems (configuration, token); + } + internal protected override void OnSetFormat (MSBuildFileFormat format) { Item.OnSetFormat (format); @@ -1536,11 +1548,6 @@ namespace MonoDevelop.Projects return Item.OnCreateConfiguration (id, kind); } - internal protected override DateTime OnGetLastBuildTime (ConfigurationSelector configuration) - { - return Item.DoGetLastBuildTime (configuration); - } - internal protected override Task OnLoad (ProgressMonitor monitor) { return Item.OnLoad (monitor); @@ -1658,11 +1665,6 @@ namespace MonoDevelop.Projects return Item.OnClean (monitor, configuration, buildSession); } - internal protected override bool OnNeedsBuilding (ConfigurationSelector configuration) - { - return Item.OnGetNeedsBuilding (configuration); - } - internal protected override void OnWriteSolutionData (ProgressMonitor monitor, SlnPropertySet properties) { Item.OnWriteSolutionData (monitor, properties); diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemExtension.cs index 1642be83a3..bc7d1df926 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemExtension.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItemExtension.cs @@ -34,6 +34,7 @@ using MonoDevelop.Projects.Extensions; using System.Threading.Tasks; using System.Linq; using System.Collections.Immutable; +using System.Threading; namespace MonoDevelop.Projects { @@ -129,11 +130,17 @@ namespace MonoDevelop.Projects return next.OnGetExecutionDependencies (); } + [Obsolete ("Use the overload that returns a Task")] internal protected virtual IEnumerable<SolutionItem> OnGetReferencedItems (ConfigurationSelector configuration) { return next.OnGetReferencedItems (configuration); } + internal protected virtual Task<List<SolutionItem>> OnGetReferencedItems (ConfigurationSelector configuration, CancellationToken token) + { + return next.OnGetReferencedItems (configuration, token); + } + internal protected virtual void OnSetFormat (MSBuildFileFormat format) { next.OnSetFormat (format); @@ -174,6 +181,7 @@ namespace MonoDevelop.Projects return next.OnClean (monitor, configuration, operationContext); } + [Obsolete ("This method will be removed in future releases")] internal protected virtual bool OnNeedsBuilding (ConfigurationSelector configuration) { return next.OnNeedsBuilding (configuration); @@ -184,9 +192,10 @@ namespace MonoDevelop.Projects return next.OnBuild (monitor, configuration, operationContext); } + [Obsolete ("This method will be removed in future releases")] internal protected virtual DateTime OnGetLastBuildTime (ConfigurationSelector configuration) { - return next.OnGetLastBuildTime (configuration); + return DateTime.MinValue; } #endregion diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Workspace.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Workspace.cs index f8e469cc83..3fbf33888e 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Workspace.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Workspace.cs @@ -113,6 +113,7 @@ namespace MonoDevelop.Projects return false; } + [Obsolete ("This method will be removed in future releases")] public bool NeedsBuilding (ConfigurationSelector configuration) { return Items.OfType<IBuildTarget> ().Any (t => t.NeedsBuilding (configuration)); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs index 7d1f6727b1..f5cbce7990 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.cs @@ -455,7 +455,7 @@ namespace MonoDevelop.Ide.TypeSystem var oldProjectData = GetProjectData (projectId);
var projectData = CreateProjectData (projectId);
- var references = await CreateMetadataReferences (p, projectId, token).ConfigureAwait (false);
+ var references = await CreateReferences (p, projectId, token).ConfigureAwait (false);
if (token.IsCancellationRequested)
return null;
var config = IdeApp.Workspace != null ? p.GetConfiguration (IdeApp.Workspace.ActiveConfiguration) as MonoDevelop.Projects.DotNetProjectConfiguration : null;
@@ -483,8 +483,8 @@ namespace MonoDevelop.Ide.TypeSystem cp != null ? cp.CreateCompilationOptions () : null,
cp != null ? cp.CreateParseOptions (config) : null,
documents.Item1,
- CreateProjectReferences (p, token),
- references,
+ references.Item2,
+ references.Item1,
additionalDocuments: documents.Item2
);
projectData.Info = info;
@@ -630,100 +630,74 @@ namespace MonoDevelop.Ide.TypeSystem typeof(System.Xml.XmlDocument).Assembly.Location, // System.Xml
};
-
- static async Task<List<MetadataReference>> CreateMetadataReferences (MonoDevelop.Projects.Project proj, ProjectId projectId, CancellationToken token)
+ async Task<ValueTuple<List<MetadataReference>,List<ProjectReference>>> CreateReferences (
+ MonoDevelop.Projects.Project proj, ProjectId projectId, CancellationToken token)
{
- List<MetadataReference> result = new List<MetadataReference> ();
+ var assemblyRefs = new List<MetadataReference> ();
var netProject = proj as MonoDevelop.Projects.DotNetProject;
- if (netProject == null) {
- // create some default references for unsupported project types.
+ if (netProject == null) { + // create some default references for unsupported project types. foreach (var asm in DefaultAssemblies) {
var metadataReference = MetadataReferenceCache.LoadReference (projectId, asm);
- result.Add (metadataReference);
+ assemblyRefs.Add (metadataReference);
}
- return result;
+ return (assemblyRefs, null);
}
+
var configurationSelector = IdeApp.Workspace?.ActiveConfiguration ?? MonoDevelop.Projects.ConfigurationSelector.Default;
- var hashSet = new HashSet<string> (FilePath.PathComparer);
+ var projectRefs = new List<ProjectReference> ();
+ var assembliesHash = new HashSet<string> (FilePath.PathComparer);
+ var projectsHash = new HashSet<MonoDevelop.Projects.DotNetProject> (); + + try {
- foreach (var file in await netProject.GetReferencedAssemblies (configurationSelector, false).ConfigureAwait (false)) {
+ var references = await netProject.GetReferences (configurationSelector).ConfigureAwait (false);
+ foreach (var reference in references) {
if (token.IsCancellationRequested)
- return result;
+ return (assemblyRefs, projectRefs); + + // if it's a project reference + if (reference.IsProjectReference) {
+ if (!reference.ReferenceOutputAssembly) {
+ continue;
+ }
+ var referencedProject = reference.GetReferencedItem (proj.ParentSolution) as MonoDevelop.Projects.DotNetProject;
+ if (referencedProject == null || !projectsHash.Add (referencedProject)) {
+ continue;
+ }
+
+ if(!TypeSystemService.IsOutputTrackedProject (referencedProject)) {
+ projectRefs.Add (new ProjectReference (
+ GetOrCreateProjectId (referencedProject),
+ ImmutableArray<string>.Empty.AddRange (reference.EnumerateAliases ())));
+ continue;
+ }
+
+ //it's an output tracked project, treat it as an assembly ref
+ }
+
string fileName;
- if (!Path.IsPathRooted (file.FilePath)) {
- fileName = Path.Combine (Path.GetDirectoryName (netProject.FileName), file.FilePath);
+ if (!Path.IsPathRooted (reference.FilePath)) {
+ fileName = Path.Combine (Path.GetDirectoryName (netProject.FileName), reference.FilePath);
} else {
- fileName = file.FilePath.FullPath;
+ fileName = reference.FilePath.FullPath;
}
- if (!hashSet.Add (fileName))
+ if (!assembliesHash.Add (fileName)) {
continue;
+ }
var metadataReference = MetadataReferenceCache.LoadReference (projectId, fileName);
- if (metadataReference == null)
- continue;
- metadataReference = metadataReference.WithAliases (file.EnumerateAliases ());
- result.Add (metadataReference);
- }
- } catch (Exception e) {
- LoggingService.LogError ("Error while getting referenced assemblies", e);
- }
-
- try {
- foreach (var pr in netProject.GetReferencedItems (configurationSelector)) {
- if (token.IsCancellationRequested)
- return result;
- var referencedProject = pr as MonoDevelop.Projects.DotNetProject;
- if (referencedProject == null)
+ if (metadataReference == null) {
continue;
- if (TypeSystemService.IsOutputTrackedProject (referencedProject)) {
- var fileName = referencedProject.GetOutputFileName (configurationSelector);
- if (!hashSet.Add (fileName))
- continue;
- var metadataReference = MetadataReferenceCache.LoadReference (projectId, fileName);
- if (metadataReference != null)
- result.Add (metadataReference);
}
+ metadataReference = metadataReference.WithAliases (reference.EnumerateAliases ());
+ assemblyRefs.Add (metadataReference);
}
} catch (Exception e) {
- LoggingService.LogError ("Error while getting referenced projects", e);
- }
- return result;
- }
-
- IEnumerable<ProjectReference> CreateProjectReferences (MonoDevelop.Projects.Project p, CancellationToken token)
- {
- var netProj = p as MonoDevelop.Projects.DotNetProject;
- if (netProj == null)
- yield break;
-
- //GetReferencedAssemblyProjects returns filtered projects, like:
- //MSBuild Condtion='something'
- //pref.ReferenceOutputAssembly
- //and for iOS/Android extensions
- MonoDevelop.Projects.DotNetProject [] referencedProjects;
- try {
- referencedProjects = netProj.GetReferencedAssemblyProjects (IdeApp.Workspace?.ActiveConfiguration ?? MonoDevelop.Projects.ConfigurationSelector.Default).ToArray ();
- } catch (Exception e) {
- LoggingService.LogError ("Error while getting referenced projects.", e);
- yield break;
- };
- var addedProjects = new HashSet<MonoDevelop.Projects.DotNetProject> ();
- foreach (var pr in netProj.References.Where (pr => pr.ReferenceType == MonoDevelop.Projects.ReferenceType.Project)) {
- //But since GetReferencedAssemblyProjects is returing DotNetProject, we lose information about
- //reference Aliases, hence we have to loop over references
- var referencedProject = pr.ResolveProject (p.ParentSolution) as MonoDevelop.Projects.DotNetProject;
- if (referencedProject == null)
- continue;
- if (!referencedProjects.Contains (referencedProject))
- continue;
- if (!addedProjects.Add (referencedProject))
- continue;
- if (TypeSystemService.IsOutputTrackedProject (referencedProject))
- continue;
- var splittedAliases = (pr.Aliases ?? "").Split (new [] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
- yield return new ProjectReference (GetOrCreateProjectId (referencedProject), ImmutableArray<string>.Empty.AddRange (splittedAliases));
+ LoggingService.LogError ("Error while getting references", e);
}
+ return (assemblyRefs, projectRefs);
}
#region Open documents
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj index 1eaf799189..39b63f8b21 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj @@ -211,6 +211,9 @@ <HintPath>..\..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> <Private>False</Private> </Reference> + <Reference Include="System.ValueTuple"> + <HintPath>..\..\..\packages\System.ValueTuple.4.3.1\lib\netstandard1.0\System.ValueTuple.dll</HintPath> + </Reference> </ItemGroup> <ItemGroup> <ProjectReference Include="..\MonoDevelop.Core\MonoDevelop.Core.csproj"> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs index 19e3b067ca..8e48f16e9c 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs @@ -285,7 +285,7 @@ namespace MonoDevelop.Ide var metadataDllName = location.MetadataModule.Name; if (metadataDllName == "CommonLanguageRuntimeLibrary") metadataDllName = "corlib.dll"; - foreach (var assembly in await dn.GetReferencedAssemblies (IdeApp.Workspace.ActiveConfiguration)) { + foreach (var assembly in await dn.GetReferences (IdeApp.Workspace.ActiveConfiguration)) { if (assembly.FilePath.ToString ().IndexOf (metadataDllName, StringComparison.Ordinal) > 0) { fileName = dn.GetAbsoluteChildPath (assembly.FilePath); break; @@ -350,7 +350,7 @@ namespace MonoDevelop.Ide metadataDllName = "corlib.dll"; var dn = project as DotNetProject; if (dn != null) { - foreach (var assembly in await dn.GetReferencedAssemblies (IdeApp.Workspace.ActiveConfiguration)) { + foreach (var assembly in await dn.GetReferences (IdeApp.Workspace.ActiveConfiguration)) { if (assembly.FilePath.ToString ().IndexOf(metadataDllName, StringComparison.Ordinal) > 0) { fileName = dn.GetAbsoluteChildPath (assembly.FilePath); break; @@ -1079,7 +1079,7 @@ namespace MonoDevelop.Ide } if (buildBeforeExecuting) { - if (!await CheckAndBuildForExecute (entry, context, configuration, runConfiguration)) + if (!await CheckAndBuildForExecute (entry, context, configuration, runConfiguration, cs.Token)) return; } @@ -1329,7 +1329,7 @@ namespace MonoDevelop.Ide } } - async Task<bool> CheckAndBuildForExecute (IBuildTarget executionTarget, ExecutionContext context, ConfigurationSelector configuration, RunConfiguration runConfiguration) + async Task<bool> CheckAndBuildForExecute (IBuildTarget executionTarget, ExecutionContext context, ConfigurationSelector configuration, RunConfiguration runConfiguration, CancellationToken token) { if (currentBuildOperation != null && !currentBuildOperation.IsCompleted) { var bres = await currentBuildOperation.Task; @@ -1356,7 +1356,7 @@ namespace MonoDevelop.Ide if (buildDeps.Count != 0) buildTarget = buildDeps [0]; - bool needsBuild = FastCheckNeedsBuild (buildTarget, configuration); + bool needsBuild = await FastCheckNeedsBuild (buildTarget, configuration, token); if (!needsBuild) { return true; } @@ -1427,7 +1427,7 @@ namespace MonoDevelop.Ide return false; } - bool FastCheckNeedsBuild (IBuildTarget target, ConfigurationSelector configuration) + async Task<bool> FastCheckNeedsBuild (IBuildTarget target, ConfigurationSelector configuration, CancellationToken token) { var env = Environment.GetEnvironmentVariable ("DisableFastUpToDateCheck"); if (!string.IsNullOrEmpty (env) && env != "0" && !env.Equals ("false", StringComparison.OrdinalIgnoreCase)) @@ -1435,13 +1435,13 @@ namespace MonoDevelop.Ide var sei = target as Project; if (sei != null) { - if (sei.FastCheckNeedsBuild (configuration)) + if (await sei.FastCheckNeedsBuild (configuration, token)) return true; //TODO: respect solution level dependencies var deps = new HashSet<SolutionItem> (); - CollectReferencedItems (sei, deps, configuration); + await CollectReferencedItems (sei, deps, configuration); foreach (var dep in deps.OfType<Project> ()) { - if (dep.FastCheckNeedsBuild (configuration)) + if (await dep.FastCheckNeedsBuild (configuration, token)) return true; } return false; @@ -1450,7 +1450,7 @@ namespace MonoDevelop.Ide var sln = target as Solution; if (sln != null) { foreach (var item in sln.GetAllProjects ()) { - if (item.FastCheckNeedsBuild (configuration)) + if (await item.FastCheckNeedsBuild (configuration, token)) return true; } return false; @@ -1460,11 +1460,11 @@ namespace MonoDevelop.Ide return true; } - void CollectReferencedItems (SolutionItem item, HashSet<SolutionItem> collected, ConfigurationSelector configuration) + async Task CollectReferencedItems (SolutionItem item, HashSet<SolutionItem> collected, ConfigurationSelector configuration) { - foreach (var refItem in item.GetReferencedItems (configuration)) { + foreach (var refItem in await item.GetReferencedItems (configuration, CancellationToken.None)) { if (collected.Add (refItem)) { - CollectReferencedItems (refItem, collected, configuration); + await CollectReferencedItems (refItem, collected, configuration); } } } diff --git a/main/src/core/MonoDevelop.Ide/packages.config b/main/src/core/MonoDevelop.Ide/packages.config index 587389463f..69b4057c74 100644 --- a/main/src/core/MonoDevelop.Ide/packages.config +++ b/main/src/core/MonoDevelop.Ide/packages.config @@ -13,5 +13,6 @@ <package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" /> <package id="SharpZipLib" version="0.86.0" targetFramework="net45" /> <package id="System.IO.Compression" version="4.3.0" targetFramework="net45" /> + <package id="System.ValueTuple" version="4.3.1" targetFramework="net461" /> <package id="YamlDotNet.Signed" version="4.0.1-pre291" targetFramework="net45" /> </packages>
\ No newline at end of file diff --git a/main/tests/UnitTests/MonoDevelop.Projects/MSBuildTests.cs b/main/tests/UnitTests/MonoDevelop.Projects/MSBuildTests.cs index 8cc7111d55..cde88c5cd2 100644 --- a/main/tests/UnitTests/MonoDevelop.Projects/MSBuildTests.cs +++ b/main/tests/UnitTests/MonoDevelop.Projects/MSBuildTests.cs @@ -542,7 +542,7 @@ namespace MonoDevelop.Projects Assert.AreEqual ("Program7_test1.cs", p.Files [6].FilePath.FileName, "Item conditions are ignored"); var testRef = Path.Combine (dir, "MonoDevelop.Core.dll"); - var asms = (await p.GetReferencedAssemblies (sol.Configurations [0].Selector)).Select (ar => ar.FilePath).ToArray (); + var asms = (await p.GetReferences (sol.Configurations [0].Selector)).Select (ar => ar.FilePath).ToArray (); Assert.IsTrue (asms.Contains (testRef)); sol.Dispose (); @@ -2937,7 +2937,7 @@ namespace MonoDevelop.Projects string projFile = Util.GetSampleProject ("msbuild-tests", "aliased-references.csproj"); var p = (DotNetProject)await Services.ProjectService.ReadSolutionItem (Util.GetMonitor (), projFile); - var asms = (await p.GetReferencedAssemblies (p.Configurations [0].Selector)).ToArray (); + var asms = (await p.GetReferences (p.Configurations [0].Selector)).ToArray (); var ar = asms.FirstOrDefault (a => a.FilePath.FileName == "System.Xml.dll"); Assert.IsNotNull (ar); diff --git a/main/tests/UnitTests/MonoDevelop.Projects/ProjectTests.cs b/main/tests/UnitTests/MonoDevelop.Projects/ProjectTests.cs index ea07fa3bd9..5d0f7bf27c 100644 --- a/main/tests/UnitTests/MonoDevelop.Projects/ProjectTests.cs +++ b/main/tests/UnitTests/MonoDevelop.Projects/ProjectTests.cs @@ -36,6 +36,7 @@ using System.Threading.Tasks; using MonoDevelop.Ide.TypeSystem; using MonoDevelop.Projects.Policies; using MonoDevelop.Ide.CustomTools; +using System.Threading; namespace MonoDevelop.Projects { @@ -541,7 +542,7 @@ namespace MonoDevelop.Projects string solFile = Util.GetSampleProject ("portable-library", "portable-library.sln"); Solution sol = (Solution) await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile); var p = (DotNetProject) sol.FindProjectByName ("PortableLibrary"); - var refs = (await p.GetReferencedAssemblies (p.Configurations [0].Selector)).Select (r => r.FilePath.FileName).ToArray (); + var refs = (await p.GetReferences (p.Configurations [0].Selector)).Select (r => r.FilePath.FileName).ToArray (); sol.Dispose (); } @@ -621,7 +622,7 @@ namespace MonoDevelop.Projects var p = (DotNetProject) sol.Items [0]; p.References.Add (ProjectReference.CreateAssemblyReference ("System.Xml.Linq")); - var refs = (await p.GetReferencedAssemblies (ConfigurationSelector.Default)).ToArray (); + var refs = (await p.GetReferences (ConfigurationSelector.Default)).ToArray (); Assert.IsTrue (refs.Any (r => r.FilePath.FileName == "System.Xml.Linq.dll")); sol.Dispose (); @@ -638,11 +639,11 @@ namespace MonoDevelop.Projects var p = (DotNetProject) sol.Items [0]; // This will force the loading of the builder - (await p.GetReferencedAssemblies (ConfigurationSelector.Default)).ToArray (); + (await p.GetReferences (ConfigurationSelector.Default)).ToArray (); p.References.Add (ProjectReference.CreateAssemblyReference ("System.Xml.Linq")); - var refs = (await p.GetReferencedAssemblies (ConfigurationSelector.Default)).ToArray (); + var refs = (await p.GetReferences (ConfigurationSelector.Default)).ToArray (); // Check that the in-memory project data is used when the builder is loaded for the first time. Assert.IsTrue (refs.Any (r => r.FilePath.FileName == "System.Xml.Linq.dll")); @@ -819,8 +820,8 @@ namespace MonoDevelop.Projects Solution sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile); var p = sol.Items.FirstOrDefault (pr => pr.Name == "conditional-project-reference"); - Assert.AreEqual (2, p.GetReferencedItems ((SolutionConfigurationSelector)"DebugWin").Count ()); - Assert.AreEqual (1, p.GetReferencedItems ((SolutionConfigurationSelector)"Debug").Count ()); + Assert.AreEqual (2, (await p.GetReferencedItems ((SolutionConfigurationSelector)"DebugWin", CancellationToken.None)).Count); + Assert.AreEqual (1, (await p.GetReferencedItems ((SolutionConfigurationSelector)"Debug", CancellationToken.None)).Count); //We have intentional compile error in windowsLib project var res = await p.Build (Util.GetMonitor (), (SolutionConfigurationSelector)"DebugWin", true); @@ -1037,30 +1038,30 @@ namespace MonoDevelop.Projects var cs = new SolutionConfigurationSelector ("Debug"); - Assert.IsTrue (app.FastCheckNeedsBuild (cs)); - Assert.IsTrue (lib.FastCheckNeedsBuild (cs)); + Assert.IsTrue (await app.FastCheckNeedsBuild (cs, CancellationToken.None)); + Assert.IsTrue (await lib.FastCheckNeedsBuild (cs, CancellationToken.None)); var res = await sol.Build (Util.GetMonitor (), cs); Assert.IsFalse (res.HasErrors); - Assert.IsFalse (app.FastCheckNeedsBuild (cs)); - Assert.IsFalse (lib.FastCheckNeedsBuild (cs)); + Assert.IsFalse (await app.FastCheckNeedsBuild (cs, CancellationToken.None)); + Assert.IsFalse (await lib.FastCheckNeedsBuild (cs, CancellationToken.None)); var myClass = sol.ItemDirectory.Combine ("MyClass.cs"); File.WriteAllText (myClass, "public class MyClass { public const string Message = \"Bye\" ; }"); FileService.NotifyFileChanged (myClass); - Assert.IsTrue (app.FastCheckNeedsBuild (cs)); - Assert.IsTrue (lib.FastCheckNeedsBuild (cs)); + Assert.IsTrue (await app.FastCheckNeedsBuild (cs, CancellationToken.None)); + Assert.IsTrue (await lib.FastCheckNeedsBuild (cs, CancellationToken.None)); res = await lib.Build (Util.GetMonitor (), cs); Assert.IsFalse (res.HasErrors); - Assert.IsFalse (lib.FastCheckNeedsBuild (cs)); - Assert.IsTrue (app.FastCheckNeedsBuild (cs)); + Assert.IsFalse (await lib.FastCheckNeedsBuild (cs, CancellationToken.None)); + Assert.IsTrue (await app.FastCheckNeedsBuild (cs, CancellationToken.None)); res = await app.Build (Util.GetMonitor (), cs); Assert.IsFalse (res.HasErrors); - Assert.IsFalse (lib.FastCheckNeedsBuild (cs)); - Assert.IsFalse (app.FastCheckNeedsBuild (cs)); + Assert.IsFalse (await lib.FastCheckNeedsBuild (cs, CancellationToken.None)); + Assert.IsFalse (await app.FastCheckNeedsBuild (cs, CancellationToken.None)); sol.Dispose (); } diff --git a/main/tests/UnitTests/MonoDevelop.Projects/SolutionFolderTests.cs b/main/tests/UnitTests/MonoDevelop.Projects/SolutionFolderTests.cs index e0ede64136..b344d33eb6 100644 --- a/main/tests/UnitTests/MonoDevelop.Projects/SolutionFolderTests.cs +++ b/main/tests/UnitTests/MonoDevelop.Projects/SolutionFolderTests.cs @@ -25,10 +25,9 @@ // THE SOFTWARE. -using System; using UnitTests; using NUnit.Framework; -using MonoDevelop.Ide.Gui.Pads.ProjectPad; +using System.Linq; namespace MonoDevelop.Projects { @@ -42,7 +41,7 @@ namespace MonoDevelop.Projects var project = new MonoDevelop.CSharp.Project.CSharpProject { Name = "foo" }; folder.AddItem (project); - Assert.IsNotNull (folder.GetProjectContainingFile (project.FileName), "#1"); + Assert.IsNotNull (folder.GetProjectsContainingFile (project.FileName).Single (), "#1"); project.Dispose (); } diff --git a/main/tests/UnitTests/MonoDevelop.Projects/SolutionTests.cs b/main/tests/UnitTests/MonoDevelop.Projects/SolutionTests.cs index 5e4771232d..8a252ab2cd 100644 --- a/main/tests/UnitTests/MonoDevelop.Projects/SolutionTests.cs +++ b/main/tests/UnitTests/MonoDevelop.Projects/SolutionTests.cs @@ -397,51 +397,6 @@ namespace MonoDevelop.Projects } [Test()] - public async Task NeedsBuilding () - { - string solFile = Util.GetSampleProject ("console-with-libs", "console-with-libs.sln"); - - Solution sol = (Solution) await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile); - DotNetProject p = (DotNetProject) sol.FindProjectByName ("console-with-libs"); - Assert.IsNotNull (p); - DotNetProject lib1 = (DotNetProject) sol.FindProjectByName ("library1"); - Assert.IsNotNull (lib1); - DotNetProject lib2 = (DotNetProject) sol.FindProjectByName ("library2"); - Assert.IsNotNull (lib2); - - SolutionConfigurationSelector config = (SolutionConfigurationSelector) "Debug"; - - Assert.IsTrue (p. NeedsBuilding (config)); - Assert.IsTrue (lib1.NeedsBuilding (config)); - Assert.IsTrue (lib2.NeedsBuilding (config)); - - // Build the project and the references - - BuildResult res = await p.Build (Util.GetMonitor (), config, true); - foreach (BuildError er in res.Errors) - Console.WriteLine (er); - Assert.AreEqual (0, res.ErrorCount); - Assert.AreEqual (0, res.WarningCount); - Assert.AreEqual (3, res.BuildCount); - - Assert.IsTrue (File.Exists (Util.Combine (p.BaseDirectory, "bin", "Debug", "console-with-libs.exe"))); - Assert.IsTrue (File.Exists (Util.Combine (p.BaseDirectory, "bin", "Debug", GetMdb (p, "console-with-libs.exe")))); - Assert.IsTrue (File.Exists (Util.Combine (lib1.BaseDirectory, "bin", "Debug", "library1.dll"))); - Assert.IsTrue (File.Exists (Util.Combine (lib1.BaseDirectory, "bin", "Debug", GetMdb (lib1, "library1.dll")))); - Assert.IsTrue (File.Exists (Util.Combine (lib2.BaseDirectory, "bin", "Debug", "library2.dll"))); - Assert.IsTrue (File.Exists (Util.Combine (lib2.BaseDirectory, "bin", "Debug", GetMdb (lib2, "library2.dll")))); - - // Build the project, but not the references - - res = await p.Build (Util.GetMonitor (), config, false); - Assert.AreEqual (0, res.ErrorCount); - Assert.AreEqual (0, res.WarningCount); - Assert.AreEqual (1, res.BuildCount); - - sol.Dispose (); - } - - [Test()] public async Task BuildingAndCleaning () { string solFile = Util.GetSampleProject ("console-with-libs", "console-with-libs.sln"); @@ -756,9 +711,10 @@ namespace MonoDevelop.Projects var app = sol.GetAllItems<DotNetProject> ().FirstOrDefault (it => it.FileName.FileName == "console-with-libs.csproj"); - // The console app references an unsupported library. The build of the project should fail. + // The console app references two unsupported libraries. The build of the project should fail. res = await app.Build (Util.GetMonitor (), ConfigurationSelector.Default, true); - Assert.IsTrue (res.ErrorCount == 1); + //both libraries have errors due to the parallel build + Assert.IsTrue (res.ErrorCount == 2); // A solution build should succeed if it has unbuildable projects but those projects are not referenced by buildable projects app.References.Clear (); |