-- Copyright (c) Microsoft. All rights reserved. -- Licensed under the MIT license. See LICENSE file in the project root for full license information. {-# LANGUAGE QuasiQuotes, OverloadedStrings, RecordWildCards #-} module Language.Bond.Codegen.Cs.Types_cs ( types_cs , FieldMapping(..) , StructMapping(..) ) where import Data.Monoid import qualified Data.Foldable as F import Prelude import Data.Text.Lazy (Text) import Text.Shakespeare.Text import Language.Bond.Syntax.Types import Language.Bond.Syntax.Util import Language.Bond.Syntax.Internal import Language.Bond.Util import Language.Bond.Codegen.TypeMapping import Language.Bond.Codegen.Util import qualified Language.Bond.Codegen.Cs.Util as CS -- | C# representation of schema structs data StructMapping = Class -- ^ public partial class deriving Eq -- | Representation of schema fields in the generated C# types data FieldMapping = PublicFields | -- ^ public fields Properties | -- ^ auto-properties ReadOnlyProperties -- ^ auto-properties with private setter deriving Eq -- | Codegen template for generating definitions of C# types representing the schema. types_cs :: StructMapping -- ^ Specifies how to represent schema structs -> FieldMapping -- ^ Specifies how to represent schema fields -> MappingContext -> String -> [Import] -> [Declaration] -> (String, Text) types_cs structMapping fieldMapping cs _ _ declarations = (fileSuffix, [lt| #{CS.disableCscWarnings} #{CS.disableReSharperWarnings} namespace #{csNamespace} { using System.Collections.Generic; #{doubleLineSep 1 typeDefinition declarations} } // #{csNamespace} |]) where idl = MappingContext idlTypeMapping [] [] [] -- C# type csType = getTypeName cs csNamespace = sepBy "." toText $ getNamespace cs access = case structMapping of _ -> [lt|public |] fileSuffix = case structMapping of _ -> "_types.cs" struct = case structMapping of _ -> [lt|public partial class |] typeAttributes s = case structMapping of _ -> CS.typeAttributes cs s propertyAttributes f = case structMapping of Class -> CS.propertyAttributes cs f -- C# type definition for schema struct typeDefinition s@Struct {..} = [lt|#{typeAttributes s}#{struct}#{declName}#{params}#{maybe interface baseClass structBase}#{constraints} { #{doubleLineSep 2 property structFields}#{constructors} }|] where interface = case structMapping of _ -> mempty -- type parameters params = angles $ sepBy ", " paramName declParams -- constraints constraints = CS.paramConstraints declParams -- base callBaseCtor = getAny $ optional (foldMapFields metaField) structBase baseClass x = [lt| : #{csType x}|] baseCtor = if not callBaseCtor then mempty else [lt| : base(fullName, name)|] -- default value csDefault = CS.defaultValue cs -- constructors constructors = if noCtor then mempty else [lt| public #{declName}() : this("#{getDeclTypeName idl s}", "#{declName}") {} protected #{declName}(string fullName, string name)#{baseCtor} { #{newlineSep 3 initializer structFields} }|] where noCtor = not callBaseCtor && (fieldMapping == PublicFields && noMetaFields || null structFields) noMetaFields = not $ getAny $ F.foldMap metaField structFields -- property or field property f@Field {..} = [lt|#{propertyAttributes f}#{new}#{access}#{csType fieldType} #{fieldName}#{autoPropertyOrField}|] where autoPropertyOrField = case fieldMapping of PublicFields -> [lt|#{optional fieldInitializer $ csDefault f};|] Properties -> [lt| { get; set; }|] ReadOnlyProperties -> [lt| { get; private set; }|] fieldInitializer x = [lt| = #{x}|] new = if isBaseField fieldName structBase then "new " else "" :: String -- initializers in constructor initializer f@Field {..} = optional fieldInit $ def f where fieldInit x = [lt|#{this fieldName} = #{x};|] this = if fieldName == "name" || fieldName == "fullName" then ("this." ++) else id def Field {fieldType = BT_MetaName} = Just "name" def Field {fieldType = BT_MetaFullName} = Just "fullName" def x = if fieldMapping == PublicFields then Nothing else csDefault x -- C# enum definition for schema enum typeDefinition e@Enum {..} = [lt|#{CS.typeAttributes cs e}public enum #{declName} { #{newlineSep 2 constant enumConstants} }|] where -- constant constant Constant {..} = let value x = [lt| = unchecked((int)#{x})|] in [lt|#{constantName}#{optional value constantValue},|] typeDefinition _ = mempty