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

class-plugin: Add code action for implementing instance method when default implementation doesn't work #3267

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

akshaymankar
Copy link
Contributor

@akshaymankar akshaymankar commented Oct 8, 2022

Half of what #3135 proposes

@akshaymankar akshaymankar requested a review from Ailrun as a code owner October 8, 2022 09:20
@akshaymankar akshaymankar force-pushed the class-implement-default-methods branch 2 times, most recently from b755fd4 to e5a386d Compare October 9, 2022 14:20
@michaelpj michaelpj requested a review from July541 October 9, 2022 17:03
@July541
Copy link
Collaborator

July541 commented Oct 11, 2022

Sorry for the delay, I'll review this on weekend.

@@ -207,6 +213,9 @@ isClassNodeIdentifier ident = (isNothing . identType) ident && Use `Set.member`
isClassMethodWarning :: T.Text -> Bool
isClassMethodWarning = T.isPrefixOf "• No explicit implementation for"

isInstanceMissingError :: T.Text -> Bool
isInstanceMissingError = T.isPrefixOf "• No instance for"
Copy link
Member

Choose a reason for hiding this comment

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

What if this error comes from something not in an instance definition?
If I guess correctly, this will give error responses, which is not so desirable.
I think it's probably better to have a more specific way to detect this "invalid default impl" case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, yes this produces logs like Warning | class: InternalError: No Identifier found. I am not sure what is a better way to detect this error, here are two errors:

• No instance for (Test1 X)
    arising from a use of ‘DefaultImplementation.$dmf’
• In the expression: DefaultImplementation.$dmf @(X)
  In an equation for ‘f’: f = DefaultImplementation.$dmf @(X)
  In the instance declaration for ‘Test X’
• No instance for (Show a) arising from a use of ‘show’
  Possible fix:
    add (Show a) to the context of
      the type signature for:
        foo :: forall a. a -> String
• In the expression: show
  In an equation for ‘foo’: foo = show

generated from file:

{-# LANGUAGE DefaultSignatures #-}
module DefaultImplementation where

class Test1 a where

class Test a where
  f :: a -> a
  default f :: Test1 a => a -> a
  f = id

data X = X | Y


foo :: a -> String
foo = show

instance Test X where

Do you think trying to see if there is no "Possible fix" would be better? Or should the plugin just start expecting this other case and not throw errors when it doesn't find any class identifier?

Copy link
Member

Choose a reason for hiding this comment

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

How about looking for the "In instance" part? That sounds more promising. And surely it'd be better if it doesn't report HLS errors for non-default instance resolution GHC errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense, I added a check for both now.

Copy link
Member

Choose a reason for hiding this comment

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

BTW, how does this work for something like

data X = X | Y

class Test a where
  f :: a -> String

instance Test X where
  f = show

?

let groups =
-- If the mininal def contains nothing, perhaps there are
-- default implementations of methods, so the LSP offers to
-- add stub implementations of all methods.
Copy link
Member

Choose a reason for hiding this comment

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

As we have cls, we don't need to guess whether there are default method impls or not. We can use classOpItems to get the information.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! I was not aware of classOpItems 👍

@akshaymankar akshaymankar force-pushed the class-implement-default-methods branch 2 times, most recently from 4447a49 to 7046f69 Compare October 18, 2022 07:26
@akshaymankar akshaymankar force-pushed the class-implement-default-methods branch from 7046f69 to f1e6bdb Compare October 18, 2022 15:44
@fendor
Copy link
Collaborator

fendor commented Nov 2, 2022

@akshaymankar Anything blocking this? If not, I am going to give it a quick review and then merge it ;D

@akshaymankar
Copy link
Contributor Author

@akshaymankar Anything blocking this? If not, I am going to give it a quick review and then merge it ;D

I don't think so. Ship it if it looks good! :shipit:

Copy link
Collaborator

@fendor fendor left a comment

Choose a reason for hiding this comment

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

LGTM, let's get it merged!

@fendor fendor requested a review from Ailrun November 2, 2022 14:32
@fendor fendor added the merge me Label to trigger pull request merge label Nov 2, 2022

classOpItemsGroups :: Range -> [InstanceBindTypeSig] -> Class -> [[(T.Text, T.Text)]]
classOpItemsGroups range sigs cls =
concatMap (mkGroups range sigs . getName . fst) $ classOpItems cls
Copy link
Member

Choose a reason for hiding this comment

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

These are not just ones with default impl, but all methods, aren't they?

@fendor fendor removed the merge me Label to trigger pull request merge label Nov 3, 2022
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.

4 participants