Skip to content

Commit 4edf9cd

Browse files
committed
fix: include the field selector when looking for missing symbol
In GHC >= 9.8, the namespace for record selector changed and is now part of a new namespace. This allows for duplicated record field names in the same module. This hence generated a few issues in HLS when looking for a symbol using `lookupOccEnv`: the current implementation was only doing lookup in type, data and var namespaces. This commit uses `lookupOccEnv_AllNameSpaces`, so it may be more efficient (one lookup instead of two), but it also incluse the symbols from record field selectors and this will actually fix most import suggestion logic when a record field selector is not found. Note that the function is not available in `ghc` <= 9.6, hence the `CPP` and fallsback implementation, which uses the previous implementation. See https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.8#new-namespace-for-record-fields
1 parent 0218e46 commit 4edf9cd

File tree

1 file changed

+23
-2
lines changed
  • plugins/hls-refactor-plugin/src/Development/IDE/Plugin

1 file changed

+23
-2
lines changed

plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs

+23-2
Original file line numberDiff line numberDiff line change
@@ -1574,13 +1574,34 @@ extractQualifiedModuleNameFromMissingName (T.strip -> missing)
15741574
modNameP = fmap snd $ RE.withMatched $ conIDP `sepBy1` RE.sym '.'
15751575

15761576

1577+
-- | A Backward compatible implementation of `lookupOccEnv_AllNameSpaces` for
1578+
-- GHC <=9.6
1579+
--
1580+
-- It looks for a symbol name in all known namespaces, including types,
1581+
-- variables, and fieldnames.
1582+
--
1583+
-- Note that on GHC >= 9.8, the record selectors are not in the `mkVarOrDataOcc`
1584+
-- anymore, but are in a custom namespace, see
1585+
-- https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.8#new-namespace-for-record-fields,
1586+
-- hence we need to use this "AllNamespaces" implementation, otherwise we'll
1587+
-- miss them.
1588+
lookupOccEnvAllNamespaces :: ExportsMap -> T.Text -> [IdentInfo]
1589+
#if MIN_VERSION_ghc(9,7,0)
1590+
lookupOccEnvAllNamespaces exportsMap name = Set.toList $ mconcat (lookupOccEnv_AllNameSpaces (getExportsMap exportsMap) (mkTypeOcc name))
1591+
#else
1592+
lookupOccEnvAllNamespaces exportsMap name = maybe [] Set.toList $
1593+
lookupOccEnv (getExportsMap exportsMap) (mkVarOrDataOcc name)
1594+
<> lookupOccEnv (getExportsMap exportsMap) (mkTypeOcc name) -- look up the modified unknown name in the export map
1595+
#endif
1596+
1597+
15771598
constructNewImportSuggestions
15781599
:: ExportsMap -> (Maybe T.Text, NotInScope) -> Maybe [T.Text] -> QualifiedImportStyle -> [ImportSuggestion]
15791600
constructNewImportSuggestions exportsMap (qual, thingMissing) notTheseModules qis = nubOrdBy simpleCompareImportSuggestion
15801601
[ suggestion
15811602
| Just name <- [T.stripPrefix (maybe "" (<> ".") qual) $ notInScope thingMissing] -- strip away qualified module names from the unknown name
1582-
, identInfo <- maybe [] Set.toList $ lookupOccEnv (getExportsMap exportsMap) (mkVarOrDataOcc name)
1583-
<> lookupOccEnv (getExportsMap exportsMap) (mkTypeOcc name) -- look up the modified unknown name in the export map
1603+
1604+
, identInfo <- lookupOccEnvAllNamespaces exportsMap name -- look up the modified unknown name in the export map
15841605
, canUseIdent thingMissing identInfo -- check if the identifier information retrieved can be used
15851606
, moduleNameText identInfo `notElem` fromMaybe [] notTheseModules -- check if the module of the identifier is allowed
15861607
, suggestion <- renderNewImport identInfo -- creates a list of import suggestions for the retrieved identifier information

0 commit comments

Comments
 (0)