Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract code action #3337

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

Conversation

santiweight
Copy link
Collaborator

@santiweight santiweight commented Nov 14, 2022

This change adds a code action for extracting an expression as specified by a user's selected range. There is logic to ensure that the behavior of the plugin is as expected by ignoring any padded whitespace in the user's range.

There are currently two outstanding problems:

  1. The name of the newly created function is always newDefinition. I'm not sure how to create fresh variables. We can definitely merge with this limitation
  2. This code action does not add arguments for variables that are no longer in scope Implemented

If anyone is interested, I could use pointers on (2). I am going to try to take inspiration from wingman for now, however...

@santiweight
Copy link
Collaborator Author

@michaelpj I think you might be interested

@michaelpj
Copy link
Collaborator

Could you rebase this? I think that will make the diff nicer now your previous PR has been merged.

@santiweight santiweight force-pushed the extract-plugin branch 2 times, most recently from a45c5ee to a78fdac Compare November 20, 2022 01:38
Santiago Weight added 2 commits November 19, 2022 19:14
@santiweight
Copy link
Collaborator Author

santiweight commented Nov 20, 2022

This is now ready to review: all tests pass. I have added extensive documentation to guide the reader through my quick-and-dirty solution for finding free variables.

@ozkutuk If you're interested

I have not CPPed yet because I can imagine the code will change a fair amount during review...

@santiweight santiweight marked this pull request as ready for review November 20, 2022 03:21
@santiweight santiweight changed the title Draft: Extract code action Extract code action Nov 20, 2022
Copy link
Collaborator

@michaelpj michaelpj left a comment

Choose a reason for hiding this comment

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

Looks plausible!

ghcide/src/Development/IDE/GHC/Error.hs Outdated Show resolved Hide resolved
fromLspList :: List a -> [a]
fromLspList (List a) = a

-- | Find the text delineated by a given Range from a source Text.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this entire function can be implemented quite idiomatically using the text-rope package that we use in lsp. See here for something similar: https://github.com/haskell/lsp/blob/master/lsp/src/Language/LSP/VFS.hs#L535

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we should also export a function like this in that module that handles also trimming based on the character offsets.

-- | From a function name and list of arguments, generate a new function with the given LHsExpr as the rhs.
generateNewDecl :: Monad m => LIdP GhcPs -> [RdrName] -> LHsExpr GhcPs -> TransformT m (HsDecl GhcPs)
generateNewDecl name args expr = do
sp1 <- uniqueSrcSpanT
Copy link
Collaborator

Choose a reason for hiding this comment

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

when do you use this rather than generatedSrcSpan?

firstContainedExprQ = \case
lexpr@(L (SrcSpanAnn _ span@(RealSrcSpan realSrcSpan _)) _) :: LHsExpr GhcPs
| rangeSrcSpan <- rangeToSrcSpan (fromString $ unpackFS $ srcSpanFile realSrcSpan) (unUnpaddedRange range)
, isSameSrcSpanModuloFile rangeSrcSpan span
Copy link
Collaborator

Choose a reason for hiding this comment

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

why modulo file? Maybe we should be turning the srcspans into Ranges and comparing those instead?

import Debug.Trace (traceM, traceShowM)


pattern R :: UInt -> UInt -> UInt -> UInt -> Range
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm sure this exists somewhere else as well... suggests it should maybe go in lsp!

plugins/hls-refactor-plugin/test/Extract.hs Show resolved Hide resolved
@michaelpj
Copy link
Collaborator

Oh, and this will need doc in features.md also

-- Before:
-- foo = x + y + z
-- After
-- newDefinition y + z = y + z
Copy link
Collaborator

@ozkutuk ozkutuk Nov 25, 2022

Choose a reason for hiding this comment

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

Suggested change
-- newDefinition y + z = y + z
-- newDefinition = y + z

Santiago Weight added 3 commits December 15, 2022 18:05
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.

None yet

3 participants