feat(language-service): add linked editing ranges for HTML tag synchronization#66738
Conversation
|
@kbrilla Can you add a demo for how exactly this works? |
…onization This adds support for linked editing ranges in Angular templates, allowing VS Code to synchronize the editing of matching HTML opening and closing tags. When you rename an opening tag, the closing tag is automatically renamed too. The implementation: - Adds a new linked_editing_range.ts module - Uses the Angular template AST to find matching tag pairs - Works in both inline templates and external HTML template files - Handles components, directives, and standard HTML elements PR Close angular#66738
1434ea6 to
5d819d4
Compare
…onization This feature enables synchronized editing of opening and closing HTML tag pairs in Angular inline templates. When the cursor is on an element tag name, editing it will automatically update the corresponding tag. Implementation: - Add getLinkedEditingRangeAtPosition method to NgLanguageService interface - Implement linked editing range detection for opening and closing tags - Handle edge cases: self-closing elements, void elements, cursor detection - Export through ts_plugin wrapper to override TypeScript JSX-only implementation - For external HTML templates, VS Code built-in HTML support handles linked editing
5d819d4 to
ee36f64
Compare
What is Linked Editing?Linked editing (also known as "mirror cursor" or "rename on type") allows you to edit matching HTML tag pairs simultaneously. When you rename an opening tag, the closing tag updates automatically, and vice versa. How to EnableOption 1: Always-On (Settings)Linked editing is enabled by default in VS Code. If it's not working, check your settings:
Alternatively, add to your {
"editor.linkedEditing": true
}Option 2: On-Demand (Command)If you don't want linked editing always active, you can trigger it on-demand:
This temporarily activates linked editing for the current tag pair until you move your cursor away. How to Use
Example@Component({
template: `
<div class="container"> <!-- Place cursor on "div" here -->
<span>Hello</span>
</div> <!-- "div" here updates automatically -->
`
})
Supported Scenarios
Excluded Scenarios
Technical Details
TroubleshootingLinked editing not working in inline templates?
Works in HTML but not in TypeScript?The Angular Language Service specifically handles inline templates. Make sure:
|
|
@atscott if I could ask for You to review code again as there were issues with not overriding ts implementation of getLinkedEditingRangeAtPosition which i did not catch https://github.com/angular/angular/compare/5d819d40f66ab349fc71fdfdb7fae4c2d65a0430..ee36f64e78ee7cb0a0a4460b53d2a0ddc4682f1b#diff-d101cf9913b0899c7728f93db6b858a1fd05a0605cc0ea14dd97db2dc28a4c28 |
|
This PR was merged into the repository. The changes were merged into the following branches:
|
|
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |


PR Description
This PR adds support for Linked Editing Ranges (LSP 3.16) in the Angular Language Service to enable synchronized editing of opening and closing HTML tag pairs in Angular templates.
What is Linked Editing?
Linked editing allows users to edit matching HTML tags simultaneously. When the cursor is on an element's tag name, both the opening and closing tags are linked, so changes to one automatically update the other.
Changes
Language Service (
packages/language-service):linked_editing_range.tsimplementinggetLinkedEditingRangeAtPosition()getLinkedEditingRangeAtPositionmethod toNgLanguageServiceinterfacelanguage_service.tsVS Code Extension (
vscode-ng-language-service):linked_editing_range.tshandlertextDocument/linkedEditingRangeinsession.tslinkedEditingRangeProvidercapability ininitialization.tsFeatures
[-\w]+for valid tag namesTesting
Related
Fixes #66736
Checklist