thrift-compiler 0.2.0.0 → 0.3.0.0
raw patch · 10 files changed
+136/−13 lines, 10 filesdep ~aeson-prettydep ~extradep ~some
Dependency ranges changed: aeson-pretty, extra, some, text-show
Files
- CHANGELOG.md +5/−0
- Thrift/Compiler/GenHaskell.hs +38/−0
- Thrift/Compiler/Lexer.x +2/−1
- Thrift/Compiler/OptParse.hs +1/−0
- Thrift/Compiler/Parser.y +31/−3
- Thrift/Compiler/Types.hs +4/−4
- test/if/bidi.thrift +37/−0
- tests/if/constants.thrift +2/−0
- tests/if/no_structs.thrift +11/−0
- thrift-compiler.cabal +5/−5
CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for thrift-compiler +## 0.3.0.0++* Added parser support for 'sink' and 'stream'; both are ignored+ by the compiler+ ## 0.2.0.0 * The folly dependency is now bundled in the Hackage package folly-clib,
Thrift/Compiler/GenHaskell.hs view
@@ -12,11 +12,15 @@ , writeModule, showModule , ThriftModule(..) , commonPragmas+ , NamespacePathValidationError(..) ) where +import Control.Exception (Exception, throwIO)+import Control.Monad (unless) import Data.List import Data.List.Extra import Data.Text (Text)+import Data.Typeable (Typeable) import Language.Haskell.Exts hiding (parse, Decl, name, app) import System.Directory import System.FilePath@@ -51,17 +55,51 @@ , tmModuleName :: String } +-- | Exception thrown when a namespace directive would result in files+-- being generated outside the designated output directory+data NamespacePathValidationError = NamespacePathValidationError+ { npveOutputDir :: FilePath+ , npveGeneratedPath :: FilePath+ , npveOriginalPath :: FilePath+ } deriving (Show, Typeable)++instance Exception NamespacePathValidationError+ writeHsCode :: Options Haskell -> Program Haskell Thrift.Loc -> IO [FilePath] writeHsCode opts prog = -- Write the Generated Files mapM writeModule =<< genHsCode opts prog +-- | Validate that a generated path is contained within the output directory+-- Prevents namespace directives from writing files outside the intended+-- output directory (see T243717416)+validateOutputPath :: FilePath -> FilePath -> IO ()+validateOutputPath outputDir generatedPath = do+ -- Canonicalize both paths to resolve .., symlinks, etc.+ canonicalOutput <- canonicalizePath outputDir+ canonicalGenerated <- canonicalizePath generatedPath++ -- Check if generated path is inside output directory+ unless (canonicalOutput `isPrefixOf` canonicalGenerated) $+ throwIO $ NamespacePathValidationError+ { npveOutputDir = canonicalOutput+ , npveGeneratedPath = canonicalGenerated+ , npveOriginalPath = generatedPath+ }+ where+ isPrefixOf :: FilePath -> FilePath -> Bool+ isPrefixOf prefix path =+ let prefix' = addTrailingPathSeparator prefix+ path' = addTrailingPathSeparator path+ in prefix' `Data.List.isPrefixOf` path'+ genHsCode :: Options Haskell -> Program Haskell Thrift.Loc -> IO [ThriftModule] genHsCode Options{..} prog@Program{..} = do let progHSPath = Text.unpack $ Text.replace "." "/" progHSName HsOpts{..} = optsLangSpecific dir = progOutPath </> hsoptsGenPrefix </> progHSPath+ validateOutputPath optsOutPath dir relativeDir <- makeRelativeToCurrentDirectory dir let
Thrift/Compiler/Lexer.x view
@@ -80,6 +80,7 @@ "binary" { basicToken BINARY } "senum" { basicToken SENUM } "stream" { basicToken STREAM }+ "sink" { basicToken SINK } "void" { basicToken VOID } "union" { basicToken UNION } "view" { basicToken VIEW }@@ -160,7 +161,7 @@ | SYMBOL String | TRUE | FALSE -- Stuff we don't use (yet)- | SENUM | STREAM | VOID | BINARY | INTERACTION+ | SENUM | STREAM | VOID | BINARY | INTERACTION | SINK | UNION | VIEW | EXCEPTION | SERVICE | ONEWAY | EXTENDS | THROWS | ASYNC | PERFORMS | SAFE | TRANSIENT | STATEFUL | PERMANENT | SERVER | CLIENT
Thrift/Compiler/OptParse.hs view
@@ -97,6 +97,7 @@ _ <- switch (long "allow-neg-keys") _ <- switch (long "allow-neg-enum-vals") _ <- maybeStr [long "templates"]+ _ <- maybeStr [long "extra-validation"] pure $ case lo of TheseLangOpts optsLangSpecific -> TheseOptions Options{..}
Thrift/Compiler/Parser.y view
@@ -76,6 +76,7 @@ binary { Tok BINARY _ } senum { Tok SENUM _ } stream { Tok STREAM _ }+ sink { Tok SINK _ } interaction { Tok INTERACTION _ } void { Tok VOID _ } union { Tok UNION _ }@@ -134,13 +135,22 @@ } | StructuredAnnotations package stringLit { Just HPackage- { pkgUri = lParsed $3+ { pkgUri = Just (lParsed $3) , pkgKeywordLoc = getLoc $2- , pkgUriLoc = lLoc $3- , pkgQuoteType = lRep $3+ , pkgUriLoc = Just (lLoc $3)+ , pkgQuoteType = Just (lRep $3) , pkgSAnns = $1 } }+ | StructuredAnnotations package ';'+ { Just HPackage+ { pkgUri = Nothing+ , pkgKeywordLoc = getLoc $2+ , pkgUriLoc = Nothing+ , pkgQuoteType = Nothing+ , pkgSAnns = $1+ }+ } Include : include { L (getLoc $1) Include }@@ -616,6 +626,22 @@ , rsStream = (Stream tStream $6 (annTy1 $3 $4 $7)) } }+ | sink '<' AnnotatedType Throws '>' ',' stream '<' AnnotatedType Throws '>'+ { case $9 of+ Some t -> ResponseAndStreamReturn+ { rsReturn = Nothing+ , rsComma = Nothing+ , rsStream = (Stream t $10 (annTy1 $7 $8 $11))+ }+ }+ | AnnotatedType ',' sink '<' AnnotatedType Throws '>' ',' stream '<' AnnotatedType Throws '>'+ { case $11 of+ Some t -> ResponseAndStreamReturn+ { rsReturn = Nothing+ , rsComma = Nothing+ , rsStream = (Stream t $12 (annTy1 $9 $10 $13))+ }+ } Throw :: { Parsed (Field 'ThrowsField) } Throw : StructuredAnnotations intLit ':' AnnotatedType Symbol MaybeConst Annotations Separator@@ -707,6 +733,8 @@ | readonly { L (getLoc $1) "readonly" } | idempotent { L (getLoc $1) "idempotent" } | package { L (getLoc $1) "package" }+ | sink { L (getLoc $1) "sink" }+ | stream { L (getLoc $1) "stream" } stringLit : stringTok {% case $1 of
Thrift/Compiler/Types.hs view
@@ -118,10 +118,10 @@ , nmQuoteType :: Maybe QuoteType } | HPackage- { pkgUri :: Text+ { pkgUri :: Maybe Text , pkgKeywordLoc :: Located a- , pkgUriLoc :: Located a- , pkgQuoteType :: QuoteType+ , pkgUriLoc :: Maybe (Located a)+ , pkgQuoteType :: Maybe QuoteType , pkgSAnns :: [StructuredAnnotation s l a] } @@ -855,7 +855,7 @@ -> SCHEMA l 'StructSchema s -> SCHEMA l 'StructSchema ('(name, Maybe t) ': s) --- | Renamed for target langauge+-- | Renamed for target language data Name = Name { sourceName :: ThriftName , resolvedName :: Name_ 'Resolved
+ test/if/bidi.thrift view
@@ -0,0 +1,37 @@+/*+ * Copyright (c) Meta Platforms, Inc. and affiliates.+ * All rights reserved.+ *+ * This source code is licensed under the BSD-style license found in the+ * LICENSE file in the root directory of this source tree.+ */++namespace cpp2 apache.thrift.detail.test++exception BiDiSinkException {+ 1: string message;+}++exception BiDiStreamException {+ 1: string message;+}++exception BiDiMethodException {+ 1: string message;+}++service TestBiDiService {+ // @lint-ignore THRIFTCHECKS new unreleased feature+ sink<string>, stream<string> echo();++ // @lint-ignore THRIFTCHECKS new unreleased feature+ string, sink<string>, stream<string> echoWithResponse(1: string initial);++ // @lint-ignore THRIFTCHECKS new unreleased feature+ sink<i64>, stream<i64> intStream();++ // @lint-ignore THRIFTCHECKS new unreleased feature+ sink<i64 throws (1: BiDiSinkException sinkEx)>, stream<+ i64 throws (1: BiDiStreamException sinkEx)+ > canThrow() throws (1: BiDiMethodException methodEx);+}
tests/if/constants.thrift view
@@ -6,6 +6,8 @@ * LICENSE file in the root directory of this source tree. */ +// include "thrift/annotation/thrift.thrift"+ const i32 i32Const = 99; const bool boolConst = 0;
+ tests/if/no_structs.thrift view
@@ -0,0 +1,11 @@+/*+ * Copyright (c) Meta Platforms, Inc. and affiliates.+ * All rights reserved.+ *+ * This source code is licensed under the BSD-style license found in the+ * LICENSE file in the root directory of this source tree.+ */++include "if/foo.thrift"++const foo.Foo fooConst = {"foo2": true};
thrift-compiler.cabal view
@@ -3,7 +3,7 @@ -- Copyright (c) Facebook, Inc. and its affiliates. name: thrift-compiler-version: 0.2.0.0+version: 0.3.0.0 synopsis: A compiler from the Thrift Interface Definition Language (IDL) to Haskell homepage: https://github.com/facebookincubator/hsthrift bug-reports: https://github.com/facebookincubator/hsthrift/issues@@ -94,12 +94,12 @@ array >= 0.5.3 && < 0.6, mtl >= 2.2.2 && < 2.4, optparse-applicative >= 0.17 && < 0.19,- aeson-pretty >= 0.8.10 && < 0.9,+ aeson-pretty >= 0.8.9 && < 0.9, either >= 5.0.2 && < 5.1,- extra >= 1.8 && < 1.9,+ extra >= 1.7.14 && < 1.9, fb-util >= 0.1.0 && < 0.3,- some >= 1.0.6 && < 1.1,- text-show >= 3.10.5 && < 3.11,+ some >= 1.0.4 && < 1.1,+ text-show >= 3.10.4 && < 3.11, haskell-src-exts >=1.20.3 && <1.24, haskell-names < 0.10, base >=4.11.1 && <4.20,