git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Better error for invalid FFI identifiers, #2011
23b6160Harry Garrood
src/Language/PureScript/Errors.hs+9
@@ -46,6 +46,7 @@ data SimpleErrorMessage
46 | UnnecessaryFFIModule ModuleName FilePath
46 | UnnecessaryFFIModule ModuleName FilePath
47 | MissingFFIImplementations ModuleName [Ident]
47 | MissingFFIImplementations ModuleName [Ident]
48 | UnusedFFIImplementations ModuleName [Ident]
48 | UnusedFFIImplementations ModuleName [Ident]
49+ | InvalidFFIIdentifier ModuleName String
49 | CannotGetFileInfo FilePath
50 | CannotGetFileInfo FilePath
50 | CannotReadFile FilePath
51 | CannotReadFile FilePath
51 | CannotWriteFile FilePath
52 | CannotWriteFile FilePath
@@ -229,6 +230,7 @@ errorCode em = case unwrapErrorMessage em of
229 UnnecessaryFFIModule{} -> "UnnecessaryFFIModule"
230 UnnecessaryFFIModule{} -> "UnnecessaryFFIModule"
230 MissingFFIImplementations{} -> "MissingFFIImplementations"
231 MissingFFIImplementations{} -> "MissingFFIImplementations"
231 UnusedFFIImplementations{} -> "UnusedFFIImplementations"
232 UnusedFFIImplementations{} -> "UnusedFFIImplementations"
233+ InvalidFFIIdentifier{} -> "InvalidFFIIdentifier"
232 CannotGetFileInfo{} -> "CannotGetFileInfo"
234 CannotGetFileInfo{} -> "CannotGetFileInfo"
233 CannotReadFile{} -> "CannotReadFile"
235 CannotReadFile{} -> "CannotReadFile"
234 CannotWriteFile{} -> "CannotWriteFile"
236 CannotWriteFile{} -> "CannotWriteFile"
@@ -552,6 +554,13 @@ prettyPrintSingleError full level showWiki e = flip evalState defaultUnknownMap
552 paras [ line $ "The following definitions in the foreign module for module " ++ runModuleName mn ++ " are unused: "
554 paras [ line $ "The following definitions in the foreign module for module " ++ runModuleName mn ++ " are unused: "
553 , indent . paras $ map (line . runIdent) idents
555 , indent . paras $ map (line . runIdent) idents
554 ]
556 ]
557+ renderSimpleErrorMessage (InvalidFFIIdentifier mn ident) =
558+ paras [ line $ "In the FFI module for " ++ runModuleName mn ++ ":"
559+ , indent . paras $
560+ [ line $ "The identifier `" ++ ident ++ "` is not valid in PureScript."
561+ , line "Note that exported identifiers in FFI modules must be valid PureScript identifiers."
562+ ]
563+ ]
555 renderSimpleErrorMessage (MultipleFFIModules mn paths) =
564 renderSimpleErrorMessage (MultipleFFIModules mn paths) =
556 paras [ line $ "Multiple foreign module implementations have been provided for module " ++ runModuleName mn ++ ": "
565 paras [ line $ "Multiple foreign module implementations have been provided for module " ++ runModuleName mn ++ ": "
557 , indent . paras $ map line paths
566 , indent . paras $ map line paths
src/Language/PureScript/Make.hs+20−6
@@ -42,6 +42,7 @@ import Control.Concurrent.Lifted as C
42
42
43import Data.List (foldl', sort)
43import Data.List (foldl', sort)
44import Data.Maybe (fromMaybe, catMaybes, isJust)
44import Data.Maybe (fromMaybe, catMaybes, isJust)
45+import Data.Either (partitionEithers)
45import Data.Time.Clock
46import Data.Time.Clock
46import Data.String (fromString)
47import Data.String (fromString)
47import Data.Foldable (for_)
48import Data.Foldable (for_)
@@ -417,11 +418,10 @@ checkForeignDecls m path = do
417 js <- either (errorParsingModule . Bundle.UnableToParseModule) pure $ JS.parse jsStr path
418 js <- either (errorParsingModule . Bundle.UnableToParseModule) pure $ JS.parse jsStr path
418
419
419 foreignIdentsStrs <- either errorParsingModule pure $ getExps js
420 foreignIdentsStrs <- either errorParsingModule pure $ getExps js
420− let foreignIdents =
421+ foreignIdents <- either
421− either
422+ errorInvalidForeignIdentifiers
422− (internalError . ("checkForeignDecls: unexpected idents: " ++) . show)
423− S.fromList
423+ (pure . S.fromList)
424− (traverse parseIdent foreignIdentsStrs)
424+ (parseIdents foreignIdentsStrs)
425 let importedIdents = S.fromList $ map fst (CF.moduleForeign m)
425 let importedIdents = S.fromList $ map fst (CF.moduleForeign m)
426
426
427 let unusedFFI = foreignIdents S.\\ importedIdents
427 let unusedFFI = foreignIdents S.\\ importedIdents
@@ -443,10 +443,24 @@ checkForeignDecls m path = do
443 getExps :: JS.JSAST -> Either Bundle.ErrorMessage [String]
443 getExps :: JS.JSAST -> Either Bundle.ErrorMessage [String]
444 getExps = Bundle.getExportedIdentifiers (runModuleName mname)
444 getExps = Bundle.getExportedIdentifiers (runModuleName mname)
445
445
446+ errorInvalidForeignIdentifiers :: [String] -> SupplyT Make a
447+ errorInvalidForeignIdentifiers =
448+ throwError . mconcat . map (errorMessage . InvalidFFIIdentifier mname)
449+
450+ parseIdents :: [String] -> Either [String] [Ident]
451+ parseIdents strs =
452+ case partitionEithers (map parseIdent strs) of
453+ ([], idents) ->
454+ Right idents
455+ (errs, _) ->
456+ Left errs
457+
446 -- TODO: Handling for parenthesised operators should be removed after 0.9.
458 -- TODO: Handling for parenthesised operators should be removed after 0.9.
459+ -- We ignore the error message here, just being told it's an invalid
460+ -- identifier should be enough.
447 parseIdent :: String -> Either String Ident
461 parseIdent :: String -> Either String Ident
448 parseIdent str = try str <|> try ("(" ++ str ++ ")")
462 parseIdent str = try str <|> try ("(" ++ str ++ ")")
449 where
463 where
450− try s = either (Left . show) Right $ do
464+ try s = either (const (Left str)) Right $ do
451 ts <- PSParser.lex "" s
465 ts <- PSParser.lex "" s
452 PSParser.runTokenParser "" (PSParser.parseIdent <* Parsec.eof) ts
466 PSParser.runTokenParser "" (PSParser.parseIdent <* Parsec.eof) ts