/// <summary> /// Gets the items of the specified type that are visible in the current scope. /// If no match is found, returns null. /// Caller must not modify the group returned. /// </summary> internal BuildItemGroup GetItems(string name) { // The visible items consist of the adds (accumulated as we go down) // plus the first set of regular items we encounter // minus any removes BuildItemGroup allAdds = null; BuildItemGroup allRemoves = null; Dictionary <BuildItem, Dictionary <string, string> > allModifies = null; BuildItemGroup groupFound = null; foreach (LookupEntry entry in lookupEntries) { // Accumulate adds while we look downwards if (entry.Adds != null) { BuildItemGroup adds = (BuildItemGroup)entry.Adds[name]; if (adds != null) { allAdds = CreateItemGroupIfNecessary(allAdds); allAdds.ImportItems(adds); } } // Accumulate removes while we look downwards if (entry.Removes != null) { BuildItemGroup removes = (BuildItemGroup)entry.Removes[name]; if (removes != null) { allRemoves = CreateItemGroupIfNecessary(allRemoves); allRemoves.ImportItems(removes); } } // Accumulate modifications as we look downwards if (entry.Modifies != null) { Dictionary <BuildItem, Dictionary <string, string> > modifies; if (entry.Modifies.TryGetValue(name, out modifies)) { if (allModifies == null) { allModifies = new Dictionary <BuildItem, Dictionary <string, string> >(); } // We already have some modifies for this type foreach (KeyValuePair <BuildItem, Dictionary <string, string> > modify in modifies) { // If earlier scopes modify the same metadata on the same item, // they have priority MergeModificationsIntoModificationTable(allModifies, modify, ModifyMergeType.FirstWins); } } } if (entry.Items != null) { groupFound = (BuildItemGroup)entry.Items[name]; if (groupFound != null) { // Found a group: we go no further break; } } if (entry.TruncateLookupsAtThisScope) { break; } } if ((allAdds == null || allAdds.Count == 0) && (allRemoves == null || allRemoves.Count == 0) && (allModifies == null || allModifies.Count == 0)) { // We can just hand out this group verbatim - // that avoids any importing if (groupFound == null) { groupFound = new BuildItemGroup(); } return(groupFound); } // We have adds and/or removes and/or modifies to incorporate. // We can't modify the group, because that might // be visible to other batches; we have to create // a new one. BuildItemGroup result = new BuildItemGroup(); if (groupFound != null) { result.ImportItems(groupFound); } // Removes are processed after adds; this means when we remove there's no need to concern ourselves // with the case where the item being removed is in an add table somewhere. The converse case is not possible // using a project file: a project file cannot create an item that was already removed, it can only create // a unique new item. if (allAdds != null) { result.ImportItems(allAdds); } if (allRemoves != null) { result.RemoveItems(allRemoves); } // Modifies can be processed last; if a modified item was removed, the modify will be ignored if (allModifies != null) { ApplyModifies(result, allModifies); } return(result); }