/// <summary> /// Get hover content for an <see cref="MSBuildUnusedItemGroup"/>. /// </summary> /// <param name="unusedItemGroup"> /// The <see cref="MSBuildUnusedItemGroup"/>. /// </param> /// <returns> /// The content, or <c>null</c> if no content is provided. /// </returns> public MarkedStringContainer UnusedItemGroup(MSBuildUnusedItemGroup unusedItemGroup) { if (unusedItemGroup == null) { throw new ArgumentNullException(nameof(unusedItemGroup)); } string condition = unusedItemGroup.Condition; string evaluatedCondition = _projectDocument.MSBuildProject.ExpandString(condition); List <MarkedString> content = new List <MarkedString> { $"Unused Item Group: `{unusedItemGroup.OriginatingElement.ItemType}` (condition is false)" }; string itemTypeHelp = MSBuildSchemaHelp.ForItemType(unusedItemGroup.Name); if (itemTypeHelp != null) { content.Add(itemTypeHelp); } StringBuilder descriptionContent = new StringBuilder(); string[] includes = unusedItemGroup.Includes.ToArray(); descriptionContent.AppendLine( $"Include: `{unusedItemGroup.OriginatingElement.Include}` " ); descriptionContent.AppendLine(); descriptionContent.Append( $"Would have evaluated to {unusedItemGroup.Items.Count} item" ); if (!unusedItemGroup.HasSingleItem) { descriptionContent.Append("s"); } descriptionContent.AppendLine(":"); foreach (string include in includes.Take(5)) { // TODO: Consider making hyperlinks for includes that map to files which exist. descriptionContent.AppendLine( $"* `{include}`" ); } if (includes.Length > 5) { descriptionContent.AppendLine("* ..."); } content.Add( descriptionContent.ToString() ); return(new MarkedStringContainer(content)); }
/// <summary> /// Get hover content for a metadata attribute of an <see cref="MSBuildUnusedItemGroup"/>. /// </summary> /// <param name="itemGroup"> /// The <see cref="MSBuildUnusedItemGroup"/>. /// </param> /// <param name="metadataName"> /// The name of the metadata attribute. /// </param> /// <returns> /// The content, or <c>null</c> if no content is provided. /// </returns> public MarkedStringContainer UnusedItemGroupMetadata(MSBuildUnusedItemGroup itemGroup, string metadataName) { if (itemGroup == null) { throw new ArgumentNullException(nameof(itemGroup)); } if (String.IsNullOrWhiteSpace(metadataName)) { throw new ArgumentException("Argument cannot be null, empty, or entirely composed of whitespace: 'metadataName'.", nameof(metadataName)); } if (itemGroup.Name == "PackageReference") { return(UnusedItemGroup(itemGroup)); } if (metadataName == "Condition") { return(Condition(itemGroup.Name, itemGroup.FirstItem.Xml.Condition)); } if (metadataName == "Include") { metadataName = "Identity"; } List <MarkedString> content = new List <MarkedString> { $"Unused Item Metadata: `{itemGroup.Name}.{metadataName}` (item condition is false)" }; string metadataHelp = MSBuildSchemaHelp.ForItemMetadata(itemGroup.Name, metadataName); if (metadataHelp != null) { content.Add(metadataHelp); } string[] metadataValues = itemGroup.GetMetadataValues(metadataName).Where( value => !String.IsNullOrWhiteSpace(value) ) .Distinct() .ToArray(); StringBuilder metadataContent = new StringBuilder(); if (metadataValues.Length > 0) { metadataContent.AppendLine("Values:"); foreach (string metadataValue in metadataValues) { metadataContent.AppendLine( $"* `{metadataValue}`" ); } } else { metadataContent.AppendLine("No values are present for this metadata."); } content.Add( metadataContent.ToString() ); return(new MarkedStringContainer(content)); }