doc(Comments): support auto generate attribute table component in extensions#7524
doc(Comments): support auto generate attribute table component in extensions#7524
Conversation
|
Thanks for your PR, @Copilot. Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
Co-authored-by: ArgoZhang <22001478+ArgoZhang@users.noreply.github.com>
Co-authored-by: ArgoZhang <22001478+ArgoZhang@users.noreply.github.com>
# Conflicts: # src/BootstrapBlazor.Server/Components/Samples/Alerts.razor # src/BootstrapBlazor.Server/Components/Samples/AnchorLinks.razor # src/BootstrapBlazor.Server/Components/Samples/Anchors.razor # src/BootstrapBlazor.Server/Components/Samples/AutoCompletes.razor # src/BootstrapBlazor.Server/Components/Samples/AutoFills.razor # src/BootstrapBlazor.Server/Components/Samples/AutoFills.razor.cs # src/BootstrapBlazor.Server/Components/Samples/AutoRedirects.razor # src/BootstrapBlazor.Server/Components/Samples/AutoRedirects.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Avatars.razor # src/BootstrapBlazor.Server/Components/Samples/Badges.razor # src/BootstrapBlazor.Server/Components/Samples/BarcodeGenerators.razor # src/BootstrapBlazor.Server/Components/Samples/BarcodeGenerators.razor.cs # src/BootstrapBlazor.Server/Components/Samples/BarcodeReaders.razor # src/BootstrapBlazor.Server/Components/Samples/BarcodeReaders.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Blocks.razor # src/BootstrapBlazor.Server/Components/Samples/Buttons.razor # src/BootstrapBlazor.Server/Components/Samples/Buttons.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Calendars.razor # src/BootstrapBlazor.Server/Components/Samples/Cameras.razor # src/BootstrapBlazor.Server/Components/Samples/Captchas.razor # src/BootstrapBlazor.Server/Components/Samples/Captchas.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Cards.razor # src/BootstrapBlazor.Server/Components/Samples/Cards.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Carousels.razor # src/BootstrapBlazor.Server/Components/Samples/Cascaders.razor # src/BootstrapBlazor.Server/Components/Samples/Charts/Index.razor # src/BootstrapBlazor.Server/Components/Samples/Charts/Index.razor.cs # src/BootstrapBlazor.Server/Components/Samples/CheckboxLists.razor # src/BootstrapBlazor.Server/Components/Samples/Checkboxs.razor # src/BootstrapBlazor.Server/Components/Samples/Checkboxs.razor.cs # src/BootstrapBlazor.Server/Components/Samples/CherryMarkdowns.razor # src/BootstrapBlazor.Server/Components/Samples/Circles.razor # src/BootstrapBlazor.Server/Components/Samples/ClockPickers.razor # src/BootstrapBlazor.Server/Components/Samples/Collapses.razor # src/BootstrapBlazor.Server/Components/Samples/ColorPickers.razor # src/BootstrapBlazor.Server/Components/Samples/Consoles.razor # src/BootstrapBlazor.Server/Components/Samples/CountButtons.razor # src/BootstrapBlazor.Server/Components/Samples/CountUps.razor # src/BootstrapBlazor.Server/Components/Samples/CountUps.razor.cs # src/BootstrapBlazor.Server/Components/Samples/DateTimePickers.razor # src/BootstrapBlazor.Server/Components/Samples/DateTimeRanges.razor # src/BootstrapBlazor.Server/Components/Samples/DialButtons.razor # src/BootstrapBlazor.Server/Components/Samples/Dialogs.razor # src/BootstrapBlazor.Server/Components/Samples/Displays.razor # src/BootstrapBlazor.Server/Components/Samples/Dividers.razor # src/BootstrapBlazor.Server/Components/Samples/DockViews/Index.razor # src/BootstrapBlazor.Server/Components/Samples/DragDrops.razor # src/BootstrapBlazor.Server/Components/Samples/DragDrops.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Drawers.razor # src/BootstrapBlazor.Server/Components/Samples/Drawers.razor.cs # src/BootstrapBlazor.Server/Components/Samples/DropdownWidgets.razor # src/BootstrapBlazor.Server/Components/Samples/Dropdowns.razor # src/BootstrapBlazor.Server/Components/Samples/Dropdowns.razor.cs # src/BootstrapBlazor.Server/Components/Samples/EditDialogs.razor # src/BootstrapBlazor.Server/Components/Samples/EditDialogs.razor.cs # src/BootstrapBlazor.Server/Components/Samples/EditorForms.razor # src/BootstrapBlazor.Server/Components/Samples/Editors.razor # src/BootstrapBlazor.Server/Components/Samples/Empties.razor # src/BootstrapBlazor.Server/Components/Samples/ExportPdfButtons.razor # src/BootstrapBlazor.Server/Components/Samples/FileIcons.razor # src/BootstrapBlazor.Server/Components/Samples/FileViewers.razor # src/BootstrapBlazor.Server/Components/Samples/FlipClocks.razor # src/BootstrapBlazor.Server/Components/Samples/FloatingLabels.razor # src/BootstrapBlazor.Server/Components/Samples/Footers.razor # src/BootstrapBlazor.Server/Components/Samples/FullScreenButtons.razor # src/BootstrapBlazor.Server/Components/Samples/GlobalException.razor # src/BootstrapBlazor.Server/Components/Samples/GoTops.razor # src/BootstrapBlazor.Server/Components/Samples/GroupBoxes.razor # src/BootstrapBlazor.Server/Components/Samples/Handwrittens.razor # src/BootstrapBlazor.Server/Components/Samples/IFrames.razor # src/BootstrapBlazor.Server/Components/Samples/ImageCroppers.razor # src/BootstrapBlazor.Server/Components/Samples/ImageViewers.razor # src/BootstrapBlazor.Server/Components/Samples/InputNumbers.razor # src/BootstrapBlazor.Server/Components/Samples/Inputs.razor # src/BootstrapBlazor.Server/Components/Samples/IntersectionObservers.razor # src/BootstrapBlazor.Server/Components/Samples/Layouts.razor # src/BootstrapBlazor.Server/Components/Samples/Lights.razor # src/BootstrapBlazor.Server/Components/Samples/LinkButtons.razor # src/BootstrapBlazor.Server/Components/Samples/ListGroups.razor # src/BootstrapBlazor.Server/Components/Samples/ListViews.razor # src/BootstrapBlazor.Server/Components/Samples/Live2DDisplays.razor # src/BootstrapBlazor.Server/Components/Samples/Logouts.razor # src/BootstrapBlazor.Server/Components/Samples/Markdowns.razor # src/BootstrapBlazor.Server/Components/Samples/Menus.razor # src/BootstrapBlazor.Server/Components/Samples/Mermaids.razor # src/BootstrapBlazor.Server/Components/Samples/Mermaids.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Messages.razor # src/BootstrapBlazor.Server/Components/Samples/MindMaps.razor # src/BootstrapBlazor.Server/Components/Samples/Modals.razor # src/BootstrapBlazor.Server/Components/Samples/MouseFollowers.razor # src/BootstrapBlazor.Server/Components/Samples/MultiSelects.razor # src/BootstrapBlazor.Server/Components/Samples/MultiSelects.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Navigation.razor # src/BootstrapBlazor.Server/Components/Samples/OnScreenKeyboards.razor # src/BootstrapBlazor.Server/Components/Samples/OnScreenKeyboards.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Paginations.razor # src/BootstrapBlazor.Server/Components/Samples/Players.razor # src/BootstrapBlazor.Server/Components/Samples/PopoverConfirms.razor # src/BootstrapBlazor.Server/Components/Samples/PopoverConfirms.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Popovers.razor # src/BootstrapBlazor.Server/Components/Samples/Popovers.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Progress.razor # src/BootstrapBlazor.Server/Components/Samples/Progress.razor.cs # src/BootstrapBlazor.Server/Components/Samples/QRCodes.razor # src/BootstrapBlazor.Server/Components/Samples/Radios.razor # src/BootstrapBlazor.Server/Components/Samples/Rates.razor # src/BootstrapBlazor.Server/Components/Samples/Reconnectors.razor # src/BootstrapBlazor.Server/Components/Samples/Repeaters.razor # src/BootstrapBlazor.Server/Components/Samples/Responsives.razor # src/BootstrapBlazor.Server/Components/Samples/RibbonTabs.razor # src/BootstrapBlazor.Server/Components/Samples/Rows.razor # src/BootstrapBlazor.Server/Components/Samples/Scrolls.razor # src/BootstrapBlazor.Server/Components/Samples/Scrolls.razor.cs # src/BootstrapBlazor.Server/Components/Samples/SearchDialogs.razor # src/BootstrapBlazor.Server/Components/Samples/SearchDialogs.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Searches.razor # src/BootstrapBlazor.Server/Components/Samples/Segmenteds.razor # src/BootstrapBlazor.Server/Components/Samples/SelectGenerics.razor # src/BootstrapBlazor.Server/Components/Samples/SelectTables.razor # src/BootstrapBlazor.Server/Components/Samples/Selects.razor # src/BootstrapBlazor.Server/Components/Samples/SignaturePads.razor # src/BootstrapBlazor.Server/Components/Samples/Skeletons.razor # src/BootstrapBlazor.Server/Components/Samples/SlideButtons.razor # src/BootstrapBlazor.Server/Components/Samples/Sliders.razor # src/BootstrapBlazor.Server/Components/Samples/Sliders.razor.cs # src/BootstrapBlazor.Server/Components/Samples/SortableLists.razor # src/BootstrapBlazor.Server/Components/Samples/Speeches/SpeechWaves.razor # src/BootstrapBlazor.Server/Components/Samples/Spinners.razor # src/BootstrapBlazor.Server/Components/Samples/Spinners.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Splits.razor # src/BootstrapBlazor.Server/Components/Samples/Splittings.razor # src/BootstrapBlazor.Server/Components/Samples/Steps.razor # src/BootstrapBlazor.Server/Components/Samples/SweetAlerts.razor # src/BootstrapBlazor.Server/Components/Samples/SwitchButtons.razor # src/BootstrapBlazor.Server/Components/Samples/Switches.razor # src/BootstrapBlazor.Server/Components/Samples/Switches.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Tabs.razor # src/BootstrapBlazor.Server/Components/Samples/Tabs.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Tags.razor # src/BootstrapBlazor.Server/Components/Samples/TextAreas.razor # src/BootstrapBlazor.Server/Components/Samples/Timelines.razor # src/BootstrapBlazor.Server/Components/Samples/Timelines.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Timers.razor # src/BootstrapBlazor.Server/Components/Samples/Toasts.razor # src/BootstrapBlazor.Server/Components/Samples/Toggles.razor # src/BootstrapBlazor.Server/Components/Samples/Tooltips.razor # src/BootstrapBlazor.Server/Components/Samples/Tooltips.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Topologies.razor # src/BootstrapBlazor.Server/Components/Samples/Transfers.razor # src/BootstrapBlazor.Server/Components/Samples/Transfers.razor.cs # src/BootstrapBlazor.Server/Components/Samples/Transitions.razor # src/BootstrapBlazor.Server/Components/Samples/TreeViews.razor # src/BootstrapBlazor.Server/Components/Samples/TreeViews.razor.cs # src/BootstrapBlazor.Server/Components/Samples/UploadAvatars.razor # src/BootstrapBlazor.Server/Components/Samples/UploadDrops.razor # src/BootstrapBlazor.Server/Components/Samples/UploadInputs.razor # src/BootstrapBlazor.Server/Components/Samples/ValidateForms.razor # src/BootstrapBlazor.Server/Components/Samples/Vditors.razor # src/BootstrapBlazor.Server/Components/Samples/VideoPlayers.razor # src/BootstrapBlazor.Server/Components/Samples/WinBoxes.razor
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7524 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 748 749 +1
Lines 32998 32976 -22
Branches 4588 4580 -8
=========================================
- Hits 32998 32976 -22
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR migrates from manual AttributeTable Items="@GetAttributes()" declarations to using Source Generator with the Name parameter across 130+ component sample files. The migration eliminates approximately 9,000 lines of hand-maintained attribute definitions by leveraging automatic attribute extraction.
Changes:
- Replaced manual AttributeTable declarations with Source Generator-based
Nameparameter - Removed 124 obsolete GetAttributes() methods from code-behind files
- Updated ComponentAttributeCacheService to support both BootstrapBlazor and extension assemblies
- Changed AttributeItem properties from non-nullable to nullable strings
- Cleaned up orphaned XML documentation comments
- Improved XML documentation consistency in IEditorItem and EditorItem interfaces
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/BootstrapBlazor/Components/EditorForm/IEditorItem.cs | Updated XML documentation for Chinese translations to be more idiomatic |
| src/BootstrapBlazor/Components/EditorForm/EditorItem.cs | Improved XML documentation and replaced inheritdoc references |
| src/BootstrapBlazor.Server/Services/ComponentAttributeCacheService.cs | Enhanced caching logic to support both core and extension assemblies |
| src/BootstrapBlazor.Server/Data/AttributeItem.cs | Changed properties to nullable to support dynamic generation |
| src/BootstrapBlazor.Server/Components/Samples/*.razor.cs | Removed orphaned XML comments and unused variables |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// <para lang="zh">获得 绑定列的类型。</para> | ||
| /// <para lang="en">Gets the type of the bound column.</para> |
There was a problem hiding this comment.
The Chinese documentation says "获得" (get) but the property has both getter and setter based on the interface definition. The documentation should say "获得/设置" (get/set) to match the English version which correctly says "Gets or sets".
|
|
||
| var type = property.DeclaringType ?? property.PropertyType; | ||
| var typeName = type.FullName ?? $"BootstrapBlazor.Components.{type.Name}"; | ||
| var typeName = $"BootstrapBlazor.Components.{type.Name}"; |
There was a problem hiding this comment.
Line 73 hardcodes the namespace as "BootstrapBlazor.Components" but this assumes all types are in this namespace. The previous code used type.FullName ?? $"BootstrapBlazor.Components.{type.Name}" which was more flexible. For extension assemblies or types in different namespaces, this hardcoded approach could fail to find the correct XML documentation member name.
| var typeName = $"BootstrapBlazor.Components.{type.Name}"; | |
| var typeName = type.FullName ?? $"BootstrapBlazor.Components.{type.Name}"; |
| Type = GetFriendlyTypeName(property.PropertyType), | ||
| Description = GetSummary(xmlDoc, property) ?? "", | ||
| Version = GetVersion(xmlDoc, property) ?? "10.0.0", | ||
| Version = GetVersion(xmlDoc, property), |
There was a problem hiding this comment.
The Version property now returns null when xmlDoc is null or when no version is found. Previously, the code had a fallback to "10.0.0" on line 62 of the old code. Removing this default could result in null Version values being displayed in the attribute table. This may be intentional if you want to distinguish between components with and without explicit version info, but it's a behavioral change that should be considered.
| Version = GetVersion(xmlDoc, property), | |
| Version = GetVersion(xmlDoc, property) ?? "10.0.0", |
| public string? Name { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// 获得/设置 说明 | ||
| /// </summary> | ||
| public string Description { get; set; } = ""; | ||
| public string? Description { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// 获得/设置 类型 | ||
| /// </summary> | ||
| public string Type { get; set; } = ""; | ||
| public string? Type { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// 获得/设置 可选值 | ||
| /// </summary> | ||
| public string ValueList { get; set; } = ""; | ||
| public string? ValueList { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// 获得/设置 版本 | ||
| /// </summary> | ||
| public string Version { get; set; } = "10.2.2"; | ||
| public string? Version { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// 获得/设置 默认值 | ||
| /// </summary> | ||
| public string DefaultValue { get; set; } = ""; | ||
| public string? DefaultValue { get; set; } |
There was a problem hiding this comment.
The AttributeItem properties changed from non-nullable strings with default values to nullable strings. This is a breaking change if any code relies on these properties never being null. Consumers of AttributeItem may now need to handle null values, which could lead to NullReferenceExceptions if not properly handled in UI rendering code.
| var v = summaryElement.Element("inheritdoc")?.Attribute("cref")?.Value; | ||
| return v != null ? FindSummaryElement(xmlDoc, v) : summaryElement; |
There was a problem hiding this comment.
The variable name 'v' is not descriptive. It's used to store the inheritdoc reference value. Consider renaming to something more meaningful like 'inheritdocRef' or 'cref' to improve code readability.
| var v = summaryElement.Element("inheritdoc")?.Attribute("cref")?.Value; | |
| return v != null ? FindSummaryElement(xmlDoc, v) : summaryElement; | |
| var inheritdocRef = summaryElement.Element("inheritdoc")?.Attribute("cref")?.Value; | |
| return inheritdocRef != null ? FindSummaryElement(xmlDoc, inheritdocRef) : summaryElement; |
| /// <para lang="zh">获得/设置 属性类型</para> | ||
| /// <para lang="en">Gets or sets the property type</para> |
There was a problem hiding this comment.
The PropertyType property documentation says "获得/设置" (Gets or sets) but according to the IEditorItem interface (line 18), it's a get-only property. The documentation should say "获得" (Gets) to match the actual property definition in the interface.
| /// <para lang="zh">获得/设置 属性类型</para> | |
| /// <para lang="en">Gets or sets the property type</para> | |
| /// <para lang="zh">获得 属性类型</para> | |
| /// <para lang="en">Gets the property type</para> |
| /// <para lang="zh">获得/设置 是否忽略显示</para> | ||
| /// <para lang="en">Gets or sets whether the field is ignored</para> |
There was a problem hiding this comment.
The Ignore property documentation says "是否忽略显示" (whether to ignore display) but the interface documentation says "是否忽略当前编辑项" (whether to ignore the current edit item). The descriptions are inconsistent between the interface and the implementation. Consider using the more complete description from the interface or using inheritdoc.
| /// <para lang="zh">获得/设置 是否忽略显示</para> | |
| /// <para lang="en">Gets or sets whether the field is ignored</para> | |
| /// <inheritdoc cref="IEditorItem.Ignore"/> |
Issues
fixed #7574
Summary By Copilot
Regression?
Risk
Mechanical refactor using Source Generator already implemented. Attribute data source changes from manual to generated; display logic unchanged.
Verification
Server project builds with 0 errors/warnings. All 130+ components verified with correct Name mappings.
Packaging changes reviewed?
☑️ Self Check before Merge
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.