Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLluis Sanchez <llsan@microsoft.com>2018-04-04 12:47:55 +0300
committerGitHub <noreply@github.com>2018-04-04 12:47:55 +0300
commitdee7ca0fe9c8d19a44371ac5a48a89f192462495 (patch)
tree8db156a0f6a585a055a5e610edd500564644bc1f /main/src/core
parent18fb664db81ca5b91c496124a12b71a566e2c9a5 (diff)
parent72fa73bf767c905c2235006c15ff17ec43cfaa91 (diff)
Merge pull request #4325 from mono/dotnetcore-handle-duplicate-msbuild-items
[Core] Fix duplicate key restore error if duplicate files in project
Diffstat (limited to 'main/src/core')
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Collections/LookupTable.cs98
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj1
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs20
3 files changed, 113 insertions, 6 deletions
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Collections/LookupTable.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Collections/LookupTable.cs
new file mode 100644
index 0000000000..562db382ff
--- /dev/null
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Collections/LookupTable.cs
@@ -0,0 +1,98 @@
+//
+// LookupTable.cs
+//
+// Author:
+// Matt Ward <matt.ward@microsoft.com>
+//
+// Copyright (c) 2018 Microsoft
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace MonoDevelop.Core.Collections
+{
+ /// <summary>
+ /// A dictionary that allows multiple items for a single key.
+ /// </summary>
+ class LookupTable<TKey, TElement>
+ {
+ Dictionary<TKey, (TElement Item, ImmutableList<TElement>.Builder List)> lookupItems = new Dictionary<TKey, (TElement Item, ImmutableList<TElement>.Builder List)> ();
+
+ public void Add (TKey key, TElement item)
+ {
+ (TElement Item, ImmutableList<TElement>.Builder List) existingItem;
+
+ if (lookupItems.TryGetValue (key, out existingItem)) {
+ if (existingItem.List == null) {
+ existingItem.List = ImmutableList.CreateBuilder<TElement> ();
+ existingItem.List.Add (existingItem.Item);
+ // Need to add the updated tuple back to the dictionary
+ // otherwise the list is not added.
+ lookupItems [key] = existingItem;
+ }
+ existingItem.List.Add (item);
+ } else {
+ lookupItems.Add (key, (item, null));
+ }
+ }
+
+ public IEnumerable<TElement> GetItems (TKey key)
+ {
+ (TElement Item, ImmutableList<TElement>.Builder List) existingItem;
+
+ if (lookupItems.TryGetValue (key, out existingItem)) {
+ if (existingItem.List != null) {
+ return existingItem.List;
+ } else {
+ return GetSingleItemAsEnumerable (existingItem.Item);
+ }
+ }
+
+ return Enumerable.Empty<TElement> ();
+ }
+
+ IEnumerable<TElement> GetSingleItemAsEnumerable (TElement item)
+ {
+ yield return item;
+ }
+
+ public bool Remove (TKey key, TElement item)
+ {
+ (TElement Item, ImmutableList<TElement>.Builder List) existingItem;
+
+ if (lookupItems.TryGetValue (key, out existingItem)) {
+ if (existingItem.List != null) {
+ existingItem.List.Remove (item);
+ if (!existingItem.List.Any ()) {
+ lookupItems.Remove (key);
+ }
+ } else {
+ lookupItems.Remove (key);
+ }
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj
index b9d56be636..df63c58266 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj
@@ -762,6 +762,7 @@
<Compile Include="MonoDevelop.Core\StringBuilderCache.cs" />
<Compile Include="MonoDevelop.Core\ObjectPool.cs" />
<Compile Include="MonoDevelop.Core\SharedPools.cs" />
+ <Compile Include="MonoDevelop.Core.Collections\LookupTable.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Makefile.am" />
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
index 8d0e626dd4..81781f78c8 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
@@ -45,6 +45,7 @@ using MonoDevelop.Projects.Extensions;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis;
+using MonoDevelop.Core.Collections;
namespace MonoDevelop.Projects
{
@@ -2931,15 +2932,15 @@ namespace MonoDevelop.Projects
loadedItems.Clear ();
HashSet<ProjectItem> unusedItems = null;
- Dictionary<(string Name, string Include), ProjectItem> lookupItems = null;
+ LookupTable<(string Name, string Include), ProjectItem> lookupItems = null;
ImmutableList<ProjectItem>.Builder newItems = null;
if (IsReevaluating) {
unusedItems = new HashSet<ProjectItem> (Items);
- lookupItems = new Dictionary<(string Name, string Include), ProjectItem> ();
+ lookupItems = new LookupTable<(string Name, string Include), ProjectItem> ();
newItems = ImmutableList.CreateBuilder<ProjectItem> ();
// Improve ReadItem performance by creating a dictionary of items that can be
- // searched faster than using Items.FirstOrDefault. Building this dictionary takes ~15ms
+ // searched faster than using Items.FirstOrDefault. Building this dictionary takes ~17ms
foreach (var it in Items) {
if (it.BackingItem != null && it.BackingEvalItem != null) {
lookupItems.Add (GetProjectItemLookupKey (it.BackingEvalItem), it);
@@ -3006,12 +3007,14 @@ namespace MonoDevelop.Projects
productVersion = FileFormat.DefaultProductVersion;
}
- internal (ProjectItem Item, bool IsNew) ReadItem (IMSBuildItemEvaluated buildItem, Dictionary<(string Name, string Include), ProjectItem> lookupItems)
+ internal (ProjectItem Item, bool IsNew) ReadItem (IMSBuildItemEvaluated buildItem, LookupTable<(string Name, string Include), ProjectItem> lookupItems)
{
if (IsReevaluating) {
// If this item already exists in the current collection of items, reuse it
- if (lookupItems.TryGetValue (GetProjectItemLookupKey (buildItem), out ProjectItem eit)) {
- if (ItemsAreEqual (buildItem, eit.BackingEvalItem) || CheckProjectReferenceItemsAreEqual (buildItem, eit)) {
+ var key = GetProjectItemLookupKey (buildItem);
+ foreach (var eit in lookupItems.GetItems (key)) {
+ if (ItemsAreEqual (buildItem, eit)) {
+ lookupItems.Remove (key, eit);
eit.BackingItem = buildItem.SourceItem;
eit.BackingEvalItem = buildItem;
return (eit, false);
@@ -3047,6 +3050,11 @@ namespace MonoDevelop.Projects
return (item, true);
}
+ bool ItemsAreEqual (IMSBuildItemEvaluated buildItem, ProjectItem item)
+ {
+ return ItemsAreEqual (buildItem, item.BackingEvalItem) || CheckProjectReferenceItemsAreEqual (buildItem, item);
+ }
+
/// <summary>
/// Special case ProjectReference items when checking for a match for ReadItem. The underlying build
/// items may not have matching metadata properties but the ProjectReference.Equals method may