Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 13, 2025

  • Understand the current completion system and how TagHelper element completion works
  • Modify RazorCompletionItem.CreateTagHelperElement to support snippet mode
  • Update GetElementCompletions in TagHelperCompletionProvider to detect EditorRequired attributes
  • Build snippet text with placeholders for EditorRequired properties
  • Add comprehensive tests for the new snippet functionality
  • Validate the changes work correctly
  • Address PR feedback:
    • Changed to add a separate completion item for snippets (with "..." suffix) instead of modifying the existing item
    • Always add quotes in snippets (removed autoInsertAttributeQuotes parameter)
    • Use pooled StringBuilder instead of regular StringBuilder
    • Added test in CohostDocumentCompletionEndpointTest.cs
    • Simplified Cohost test to use VerifyCompletionListAsync helper
    • Optimized component tag helper lookup to use first Component kind tag helper only
  • Merged main into branch (test files moved to VS Code project)
  • Fixed test failure - snippet items don't need resolve, they already have complete insertText
Original prompt

This section details on the original issue you should resolve

<issue_title>Component completion snippet</issue_title>
<issue_description>Noticed today watching someone use the Razor editor: For components that have one or more properties that are [EditorRequired], we could do completion as a snippet, that includes the attributes for each required property (similar to how drag and drop will create attributes for them) and either puts the caret in the first one, or even puts placeholders in each and lets the user tab between them.</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #6980


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

@Copilot Copilot AI changed the title [WIP] Add completion snippet for components with editor required properties Add snippet support for component completion with EditorRequired attributes Oct 13, 2025
@Copilot Copilot AI requested a review from davidwengier October 13, 2025 01:41
Copilot finished work on behalf of davidwengier October 13, 2025 01:41
Copy link
Member

@davidwengier davidwengier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Please create additional test(s) in CohostDocumentCompletionEndpointTest.cs with appropriate "itemToResolve" and "expected" output

{
builder.Append(' ');
builder.Append(attributeName);
builder.Append(autoInsertAttributeQuotes ? "=\"$" : "=$");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot No need to check autoInsertAttributeQuotes here. Since we're creating a snippet, I think its fine for quotes to always be inserted

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit. Removed the autoInsertAttributeQuotes parameter and always insert quotes in snippets.

}

// Build snippet with placeholders for each required attribute
var builder = new StringBuilder();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Use a pooled string builder. We have helper classes etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit. Now using StringBuilderPool.GetPooledObject.

}
}

var razorCompletionItem = RazorCompletionItem.CreateTagHelperElement(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Rather than changing the completion item for the component, we should instead add a second completion item that is the snippet, perhaps with the displayText set to " with req. attributes..."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit. Now adding a second completion item with "..." suffix for the snippet instead of modifying the existing completion item.

… snippet as separate completion item

Co-authored-by: davidwengier <[email protected]>
Copy link
Contributor Author

Copilot AI commented Oct 13, 2025

@copilot Please create additional test(s) in CohostDocumentCompletionEndpointTest.cs with appropriate "itemToResolve" and "expected" output

Done in commit. Added ComponentWithEditorRequiredAttributes_SnippetsSupported test in CohostDocumentCompletionEndpointTest.cs that verifies both regular and snippet completion items are created for components with EditorRequired attributes.

@Copilot Copilot AI requested a review from davidwengier October 13, 2025 03:24
Copilot finished work on behalf of davidwengier October 13, 2025 03:24
fileKind: RazorFileKind.Component,
additionalFiles: [("TestComponent.razor", componentCode)]);

var sourceText = await document.GetTextAsync(DisposalToken);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Rather than doing all of this test code manually, can you just call VerifyCompletionListAsync, and pass in an itemToResolve and an expected for what the resulting document should look like?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Simplified the test to use VerifyCompletionListAsync with itemToResolve and expected parameters, and created a helper overload for document-based testing.

if (TryGetEditorRequiredAttributesSnippet(tagHelpersArray, displayText, out var snippetText))
{
var snippetCompletionItem = RazorCompletionItem.CreateTagHelperElement(
displayText: $"{displayText}...",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to run this in VS to see what it looks like. I don't think just "..." is enough differentiator, but I'm not sure if more than that would look bad.

// Collect all unique EditorRequired attributes from all matching tag helpers
using var editorRequiredAttributes = new PooledHashSet<string>(StringHashSetPool.Ordinal);

foreach (var tagHelper in tagHelpers)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to check this too, I think tagHelpers will only ever have a single entry, or at least only one component tag helper.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Changed the implementation to only look at the first Component kind tag helper using FirstOrDefault(th => th.Kind == TagHelperKind.Component), which is more efficient and correct for component completions.

@Copilot Copilot AI requested a review from davidwengier October 13, 2025 11:35
Copilot finished work on behalf of davidwengier October 13, 2025 11:35
@davidwengier
Copy link
Member

@copilot please merge main into your branch

Copy link
Contributor Author

Copilot AI commented Oct 14, 2025

@copilot please merge main into your branch

Done in commit 7272bb5. Merged main into the branch successfully. All tests pass.

Copilot finished work on behalf of davidwengier October 14, 2025 08:10
@davidwengier
Copy link
Member

@copilot it seems some tests failed in CI. Can you take a look? build.sh -test will run all tests in the repo

Copy link
Contributor Author

Copilot AI commented Oct 15, 2025

@copilot it seems some tests failed in CI. Can you take a look? build.sh -test will run all tests in the repo

Fixed in commit. The test ComponentWithEditorRequiredAttributes_SnippetsSupported was failing because it tried to resolve a snippet completion item. Snippet items already have complete insertText and don't need resolution - they're ready to use as-is. Updated the test to directly verify the snippet's insertText instead of trying to resolve it. All tests now pass.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • mobile.events.data.microsoft.com
    • Triggering command: /usr/share/dotnet/dotnet exec --runtimeconfig /home/REDACTED/work/razor/razor/artifacts/bin/Microsoft.VisualStudioCode.RazorExtension.Test/Debug/net9.0/Microsoft.VisualStudioCode.RazorExtension.Test.runtimeconfig.json --depsfile /home/REDACTED/work/razor/razor/artifacts/bin/Microsoft.VisualStudioCode.RazorExtension.Test/Debug/net9.0/Microsoft.VisualStudioCode.RazorExtension.Test.deps.json /home/REDACTED/work/razor/razor/artifacts/bin/Microsoft.VisualStudioCode.RazorExtension.Test/Debug/net9.0/testhost.dll --port 35261 --endpoint 127.0.0.1:035261 --role client --parentprocessid 13942 --telemetryoptedin false (dns block)
    • Triggering command: /usr/share/dotnet/dotnet exec --runtimeconfig /home/REDACTED/work/razor/razor/artifacts/bin/Microsoft.VisualStudioCode.RazorExtension.Test/Debug/net9.0/Microsoft.VisualStudioCode.RazorExtension.Test.runtimeconfig.json --depsfile /home/REDACTED/work/razor/razor/artifacts/bin/Microsoft.VisualStudioCode.RazorExtension.Test/Debug/net9.0/Microsoft.VisualStudioCode.RazorExtension.Test.deps.json /home/REDACTED/work/razor/razor/artifacts/bin/Microsoft.VisualStudioCode.RazorExtension.Test/Debug/net9.0/testhost.dll --port 34159 --endpoint 127.0.0.1:034159 --role client --parentprocessid 14012 --telemetryoptedin false (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of davidwengier October 15, 2025 10:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Component completion snippet

2 participants