Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}