Skip to content

Commit

Permalink
Merge pull request #69 from ptwales/ref-jsonEncoder
Browse files Browse the repository at this point in the history
Fix encoders referncing the primary classes encoder
  • Loading branch information
ptwales authored Jan 28, 2020
2 parents 3063629 + e387b51 commit 6b5dc9d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 15 deletions.
43 changes: 28 additions & 15 deletions src/Ccap/Codegen/Scala.purs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import Ccap.Codegen.Parser.Export as Export
import Ccap.Codegen.Shared (DelimitedLiteralDir(..), OutputSpec, delimitedLiteral, indented, modulesInScope)
import Ccap.Codegen.Types (Annotations, Exports, Module, ModuleName, Primitive(..), RecordProp, TRef, TopType(..), Type(..), TypeDecl(..), ValidatedModule, isRecord, typeDeclName, typeDeclTopType)
import Ccap.Codegen.Util (fromMaybeT, maybeT)
import Control.Monad.Maybe.Trans (MaybeT(..))
import Control.Alt (alt)
import Control.Monad.Maybe.Trans (MaybeT(..), runMaybeT)
import Control.Monad.Reader (Reader, ask, asks, runReader)
import Data.Array ((:))
import Data.Array as Array
Expand Down Expand Up @@ -40,7 +41,7 @@ modulePath mod = (Export.toPath mod.exports.scalaPkg) <> ".scala"
oneModule :: ValidatedModule -> Box
oneModule mod = do
let
modDecl = classFileType mod
modDecl = primaryClass mod

env =
{ defaultPrefix: Nothing
Expand Down Expand Up @@ -317,14 +318,14 @@ externalTypeRef importedModule importedType =
else
typeName

classFileType :: forall r. { name :: ModuleName, types :: Array TypeDecl | r } -> Maybe TypeDecl
classFileType { name, types } = Array.find (isClassFile name) types
primaryClass :: forall r. { name :: ModuleName, types :: Array TypeDecl | r } -> Maybe TypeDecl
primaryClass { name, types } = Array.find (isPrimaryClass name) types

isClassFile :: ModuleName -> TypeDecl -> Boolean
isClassFile modName typeD = modName == typeDeclName typeD && (isRecord $ typeDeclTopType typeD)
isPrimaryClass :: ModuleName -> TypeDecl -> Boolean
isPrimaryClass modName typeD = modName == typeDeclName typeD && (isRecord $ typeDeclTopType typeD)

needsQualifier :: ModuleName -> TypeDecl -> Boolean
needsQualifier modName = not <<< isClassFile modName
needsQualifier modName = not <<< isPrimaryClass modName

packageAnnotation :: Module -> Maybe String
packageAnnotation = Annotations.field "scala" "package" <<< _.annots
Expand All @@ -347,17 +348,29 @@ decoder annots = case _ of
Primitive p -> pure $ (text $ "Decoder" <> jsonPrimitive p) <<>> decoderValidations annots

jsonRef :: String -> String -> String
jsonRef which typ = "json" <> which <> typ
jsonRef which typ = "json" <> which <> typ -- should be blank if it is the primary class

jsonTypeRef :: String -> TRef -> Codegen String
jsonTypeRef which { mod, typ } =
fromMaybeT (jsonRef which typ) do
modName <- maybeT mod
extMod <- MaybeT $ askModule modName
extTypeDecl <- maybeT $ lookupTypeDecl typ extMod
let
path = Array.snoc (Array.fromFoldable $ packageAnnotation extMod) modName
pure $ prefix path $ jsonRef which $ guard (needsQualifier modName extTypeDecl) typ
let
externalJson =
runMaybeT do
modName <- maybeT mod
extMod <- MaybeT $ askModule modName
extTypeDecl <- maybeT $ lookupTypeDecl typ extMod
let
path = Array.snoc (Array.fromFoldable $ packageAnnotation extMod) modName
pure $ prefix path $ jsonRef which $ guard (needsQualifier modName extTypeDecl) typ

internalJson =
runMaybeT do
thisMod <- MaybeT $ Just <$> asks _.currentModule
decl <- maybeT $ lookupTypeDecl typ thisMod
pure $ jsonRef which $ guard (needsQualifier thisMod.name decl) typ

default = jsonRef which typ
in
alt <$> internalJson <*> externalJson <#> fromMaybe default

jsonList :: Box -> Box
jsonList json = json <<>> text ".list"
Expand Down
2 changes: 2 additions & 0 deletions test/Ccap/Codegen/Prefix.purs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ specs =
$ check "prefixInternalRef:" " prefixInternalRef: Prefix.CustomType,"
it "Don't need prefixes if defined in the companion object"
$ check "customInternalRef:" " customInternalRef: CustomType,"
it "Don't use the type suffix for encoders if they are the file's class"
$ check "\"prefix\" ->" " \"prefix\" -> jsonEncoder.encode(x.prefix),"
describe "type references" do
it "Are defined in the companion object and don't need prefixes"
$ check "type InternalRef" " type InternalRef = CustomType"
Expand Down
4 changes: 4 additions & 0 deletions test/resources/prefix/Prefix.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ type CustomRec: {
type Prefix: {
prefixInternalRef: CustomType
}

type SelfRef: {
prefix: Prefix
}

0 comments on commit 6b5dc9d

Please sign in to comment.