From 3daa2adea566309937b0f82e7604e233bc1f57a1 Mon Sep 17 00:00:00 2001 From: Dario Bertini Date: Sun, 24 Jul 2016 15:46:55 +0200 Subject: [PATCH] Fix javascript function name generation, mostly fixes #191 and remove js-specific code in servant-foreign (code which would now be dead) --- servant-foreign/src/Servant/Foreign/Inflections.hs | 2 +- servant-foreign/src/Servant/Foreign/Internal.hs | 4 +--- servant-foreign/test/Servant/ForeignSpec.hs | 2 -- servant-js/src/Servant/JS/Angular.hs | 2 +- servant-js/src/Servant/JS/Axios.hs | 2 +- servant-js/src/Servant/JS/Internal.hs | 14 ++++++++++---- servant-js/src/Servant/JS/JQuery.hs | 2 +- servant-js/src/Servant/JS/Vanilla.hs | 2 +- 8 files changed, 16 insertions(+), 14 deletions(-) diff --git a/servant-foreign/src/Servant/Foreign/Inflections.hs b/servant-foreign/src/Servant/Foreign/Inflections.hs index 759d04a0..4c0140a8 100644 --- a/servant-foreign/src/Servant/Foreign/Inflections.hs +++ b/servant-foreign/src/Servant/Foreign/Inflections.hs @@ -32,7 +32,7 @@ snakeCase :: FunctionName -> Text snakeCase = view snakeCaseL camelCaseL :: Getter FunctionName Text -camelCaseL = _FunctionName . to (convert . map (replace "-" "")) +camelCaseL = _FunctionName . to convert where convert [] = "" convert (p:ps) = mconcat $ p : map capitalize ps diff --git a/servant-foreign/src/Servant/Foreign/Internal.hs b/servant-foreign/src/Servant/Foreign/Internal.hs index 59d09436..3eced051 100644 --- a/servant-foreign/src/Servant/Foreign/Internal.hs +++ b/servant-foreign/src/Servant/Foreign/Internal.hs @@ -316,9 +316,7 @@ instance (KnownSymbol path, HasForeign lang ftype api) req & reqUrl . path <>~ [Segment (Static (PathSegment str))] & reqFuncName . _FunctionName %~ (++ [str]) where - str = - Data.Text.map (\c -> if c == '.' then '_' else c) - . pack . symbolVal $ (Proxy :: Proxy path) + str = pack . symbolVal $ (Proxy :: Proxy path) instance HasForeign lang ftype api => HasForeign lang ftype (RemoteHost :> api) where diff --git a/servant-foreign/test/Servant/ForeignSpec.hs b/servant-foreign/test/Servant/ForeignSpec.hs index 966861d5..d98e640f 100644 --- a/servant-foreign/test/Servant/ForeignSpec.hs +++ b/servant-foreign/test/Servant/ForeignSpec.hs @@ -19,8 +19,6 @@ camelCaseSpec = describe "camelCase" $ do it "converts FunctionNames to camelCase" $ do camelCase (FunctionName ["post", "counter", "inc"]) `shouldBe` "postCounterInc" - camelCase (FunctionName ["get", "hyphen-ated", "counter"]) - `shouldBe` "getHyphenatedCounter" ---------------------------------------------------------------------- diff --git a/servant-js/src/Servant/JS/Angular.hs b/servant-js/src/Servant/JS/Angular.hs index 5c93610d..896490bf 100644 --- a/servant-js/src/Servant/JS/Angular.hs +++ b/servant-js/src/Servant/JS/Angular.hs @@ -132,7 +132,7 @@ generateAngularJSWith ngOptions opts req = "\n" <> fsep = if hasService then ":" else " =" - fname = namespace <> (functionNameBuilder opts $ req ^. reqFuncName) + fname = namespace <> (toValidFunctionName (functionNameBuilder opts $ req ^. reqFuncName)) method = req ^. reqMethod url = if url' == "'" then "'/'" else url' diff --git a/servant-js/src/Servant/JS/Axios.hs b/servant-js/src/Servant/JS/Axios.hs index 3b299cd4..f0d807c4 100644 --- a/servant-js/src/Servant/JS/Axios.hs +++ b/servant-js/src/Servant/JS/Axios.hs @@ -120,7 +120,7 @@ generateAxiosJSWith aopts opts req = "\n" <> where hasNoModule = moduleName opts == "" - fname = namespace <> (functionNameBuilder opts $ req ^. reqFuncName) + fname = namespace <> (toValidFunctionName (functionNameBuilder opts $ req ^. reqFuncName)) method = T.toLower . decodeUtf8 $ req ^. reqMethod url = if url' == "'" then "'/'" else url' diff --git a/servant-js/src/Servant/JS/Internal.hs b/servant-js/src/Servant/JS/Internal.hs index f04480ea..54fda12a 100644 --- a/servant-js/src/Servant/JS/Internal.hs +++ b/servant-js/src/Servant/JS/Internal.hs @@ -120,21 +120,27 @@ toValidFunctionName t = firstChar c = prefixOK c || Set.member c firstLetterOK remainder c = prefixOK c || Set.member c remainderOK prefixOK c = c `elem` ['$','_'] - firstLetterOK = mconcat + firstLetterOK = (filterBmpChars $ mconcat [ Set.lowercaseLetter , Set.uppercaseLetter , Set.titlecaseLetter , Set.modifierLetter , Set.otherLetter , Set.letterNumber - ] + ]) remainderOK = firstLetterOK - <> mconcat + <> (filterBmpChars $ mconcat [ Set.nonSpacingMark , Set.spacingCombiningMark , Set.decimalNumber , Set.connectorPunctuation - ] + ]) + +-- Javascript identifiers can only contain codepoints in the Basic Multilingual Plane +-- that is, codepoints that can be encoded in UTF-16 without a surrogate pair (UCS-2) +-- that is, codepoints that can fit in 16-bits, up to 0xffff (65535) +filterBmpChars :: Set.CharSet -> Set.CharSet +filterBmpChars = Set.filter (< '\65536') toJSHeader :: HeaderArg f -> Text toJSHeader (HeaderArg n) diff --git a/servant-js/src/Servant/JS/JQuery.hs b/servant-js/src/Servant/JS/JQuery.hs index 98038f0c..ab07c178 100644 --- a/servant-js/src/Servant/JS/JQuery.hs +++ b/servant-js/src/Servant/JS/JQuery.hs @@ -86,7 +86,7 @@ generateJQueryJSWith opts req = "\n" <> namespace = if (moduleName opts) == "" then "var " else (moduleName opts) <> "." - fname = namespace <> (functionNameBuilder opts $ req ^. reqFuncName) + fname = namespace <> (toValidFunctionName (functionNameBuilder opts $ req ^. reqFuncName)) method = req ^. reqMethod url = if url' == "'" then "'/'" else url' diff --git a/servant-js/src/Servant/JS/Vanilla.hs b/servant-js/src/Servant/JS/Vanilla.hs index 216fbc7f..f8c1482e 100644 --- a/servant-js/src/Servant/JS/Vanilla.hs +++ b/servant-js/src/Servant/JS/Vanilla.hs @@ -97,7 +97,7 @@ generateVanillaJSWith opts req = "\n" <> namespace = if moduleName opts == "" then "var " else (moduleName opts) <> "." - fname = namespace <> (functionNameBuilder opts $ req ^. reqFuncName) + fname = namespace <> (toValidFunctionName (functionNameBuilder opts $ req ^. reqFuncName)) method = req ^. reqMethod url = if url' == "'" then "'/'" else url'