/// <summary> /// Add the MSBuild object to the locator. /// </summary> /// <param name="msbuildObject"> /// The <see cref="MSBuildObject"/>. /// </param> void Add(MSBuildObject msbuildObject) { if (msbuildObject == null) { throw new ArgumentNullException(nameof(msbuildObject)); } // Rarely, we get a duplicate item-group if the item group element is empty. // TODO: Figure out why. if (_objectsByStartPosition.TryGetValue(msbuildObject.XmlRange.Start, out MSBuildObject dupe)) { Serilog.Log.Information("Found duplicate {0} (vs {1}) at {2} (vs {3}). Same underlying object: {IdentityMatch}", msbuildObject.Kind, dupe.Kind, msbuildObject.XmlRange, dupe.XmlRange, msbuildObject.IsSameUnderlyingObject(dupe) ); if (msbuildObject is MSBuildItemGroup itemGroup1 && dupe is MSBuildItemGroup itemGroup2) { Serilog.Log.Information("Duplicate items are {Spec1} ({XmlSpec1}) vs {Spec2} ({XmlSpec2}) => {@Spec1Location} vs {@Spec2Location}", itemGroup1.FirstInclude, itemGroup1.FirstItem.Xml.Include, itemGroup2.FirstInclude, itemGroup2.FirstItem.Xml.Include, itemGroup1.FirstItem.Xml.Location, itemGroup2.FirstItem.Xml.Location ); } } _objectRanges.Add(msbuildObject.XmlRange); _objectsByStartPosition.Add(msbuildObject.XmlRange.Start, msbuildObject); }
/// <summary> /// Determine whether another <see cref="MSBuildObject"/> represents the same underlying MSBuild object. /// </summary> /// <param name="other"> /// The <see cref="MSBuildObject"/>. /// </param> /// <returns> /// <c>true</c>, if the 2 <see cref="MSBuildObject"/>s represent the same underlying MSBuild object; otherwise, <c>false</c>. /// </returns> public abstract bool IsSameUnderlyingObject(MSBuildObject other);