Skip to content

Add LSP refactoring capabilities framework - #4855

Closed
Mateusz Kadlubowski (xeho91) wants to merge 8 commits into
microsoft:mainfrom
xeho91:lsp-refactoring-capabilities
Closed

Add LSP refactoring capabilities framework#4855
Mateusz Kadlubowski (xeho91) wants to merge 8 commits into
microsoft:mainfrom
xeho91:lsp-refactoring-capabilities

Conversation

@xeho91

@xeho91 Mateusz Kadlubowski (xeho91) commented Aug 9, 2026

Copy link
Copy Markdown

Umbrella PR for the discussion #4747.
Shared base for missing refactoring code actions.

What?

  • Refactor action framework: register providers, filter by only kind, convert to LSP
  • Disabled actions gated on DisabledSupport capability + user preference
  • Fourslash test helpers:
    • VerifyRefactor
      VerifyRefactorDisabled
      VerifyRefactorWithOnly*
  • Position/line-map core extracted for offsets after edits

Why?

LSP refactoring capabilities are missing.
One base first, then add actions one PR each.


I have a draft work done for two refactoring capabilities done, which I could use as stacked PRs:

  1. Port Infer function return type refactoring capability xeho91/typescript-go#1
  2. Port Extract type refactoring capability xeho91/typescript-go#2

I couldn't create PRs for those in this repository, given that xeho91:lsp-refactoring-capabilities is a fork.

Copilot AI balanced review requested due to automatic review settings August 9, 2026 07:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds the shared LSP framework for registering, filtering, converting, and testing refactoring code actions.

Changes:

  • Adds refactor provider dispatch and LSP conversion.
  • Supports disabled actions and post-edit rename commands.
  • Adds Fourslash refactor verification helpers.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
internal/lsp/server.go Advertises refactor support.
internal/ls/lsconv/converters.go Converts offsets in arbitrary text.
internal/ls/codeactions.go Extends actions and invokes refactors.
internal/ls/codeactions_refactor.go Implements the refactor framework.
internal/ls/codeactions_refactor_test.go Tests action conversion.
internal/fourslash/fourslash.go Adds refactor test helpers.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/ls/codeactions_refactor.go Outdated
Comment thread internal/fourslash/fourslash.go
Comment thread internal/fourslash/fourslash.go
Comment thread internal/fourslash/fourslash.go
Comment thread internal/ls/codeactions_refactor.go

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

internal/ls/codeactions_refactor.go:152

  • The provider is selected using RefactorAction.Kinds, but the emitted kind is taken independently from CodeAction.Kind and defaults to refactor.rewrite. The new only-filter test registers an extract action whose factory leaves Kind empty, so a refactor.extract request returns a refactor.rewrite action, violating the request filter. Propagate/validate the registered kind, or require factories to set a kind and filter each generated action by its actual emitted kind.
	kind := action.Kind
	if kind == "" {
		kind = lsproto.CodeActionKindRefactorRewrite
	}

Comment thread internal/ls/codeactions_refactor.go

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Suppressed comments (3)

internal/fourslash/fourslash.go:2035

  • This collector accepts every refactor.* response regardless of the requested only kinds. Consequently, VerifyRefactorWithOnlyAvailable(..., refactor.extract) can treat a returned refactor.rewrite as available, bypassing the client's hierarchical filtering and allowing server-side filtering regressions to pass. Filter the collected actions by requested-kind containment.
			if item.CodeAction != nil && item.CodeAction.Kind != nil &&
				isRefactoringKind(*item.CodeAction.Kind) && item.CodeAction.Disabled == nil {
				actions = append(actions, item.CodeAction)

internal/fourslash/fourslash.go:2069

  • Using "" as the sentinel for “do not verify edits” makes an empty expected file unrepresentable. A refactor that deletes all content will skip both applying the edit and asserting the result, so the test passes without checking behavior. Use a *string or an explicit verification flag so an empty expected value remains testable.
	if options.NewFileContent != "" {
		actual := f.applyRefactorEdits(t, matchingAction, options.ApplyChanges)
		assert.Equal(t, options.NewFileContent, actual, "File content after applying refactoring did not match expected content.")

internal/ls/codeactions_refactor.go:155

  • Filtering uses RefactorAction.Kinds, but the emitted kind comes independently from CodeAction.Kind and defaults to refactor.rewrite. The new OnlyFilter test already registers an extract action whose factory omits Kind, so an only: [refactor.extract] request returns refactor.rewrite; a conforming client then filters out the action. Ensure each result inherits a matching descriptor kind, or validate its explicit kind against both the descriptor and only.
	kind := action.Kind
	if kind == "" {
		kind = lsproto.CodeActionKindRefactorRewrite

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) added the Unmigrated PR This PR was open at the time of the repo move back to TypeScript label Aug 14, 2026
@RyanCavanaugh

Copy link
Copy Markdown
Member

We're not going to be able to review this prior to the repo move back to TypeScript; closing for tracking.

@xeho91

Copy link
Copy Markdown
Author

Will it still be under consideration once I migrate my PRs to the main repository - microsoft/typescript - when the time comes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Unmigrated PR This PR was open at the time of the repo move back to TypeScript

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants