Skip to content

Commit 39bdc75

Browse files
authored
Merge pull request #159 from haskell-graphql/pedantic-builds
Make warnings fail the build
2 parents e0aeb7f + 87027f7 commit 39bdc75

File tree

12 files changed

+98
-99
lines changed

12 files changed

+98
-99
lines changed

.circleci/config.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,8 @@ jobs:
2828
- /root/.stack
2929
- .stack-work
3030
- run:
31+
# Build with --pedantic here to avoid introducing warnings. We
32+
# *don't* build with -Werror on Hackage as that is strongly
33+
# discouraged.
3134
name: Tests
32-
command: stack test --skip-ghc-check --no-terminal
35+
command: stack test --skip-ghc-check --no-terminal --pedantic

src/GraphQL/API.hs

Lines changed: 62 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@ module GraphQL.API
3434

3535
import Protolude hiding (Enum, TypeError)
3636

37-
import GraphQL.Internal.Schema hiding (Type)
38-
import qualified GraphQL.Internal.Schema (Type)
3937
import GHC.TypeLits (Symbol, KnownSymbol, TypeError, ErrorMessage(..))
38+
import qualified GraphQL.Internal.Schema as Schema
4039
import GraphQL.Internal.Name (NameError, nameFromSymbol)
4140
import GraphQL.API.Enum (GraphQLEnum(..))
4241
import GHC.Generics ((:*:)(..))
@@ -95,15 +94,15 @@ cons = (:)
9594
-- Transform into a Schema definition
9695
class HasObjectDefinition a where
9796
-- Todo rename to getObjectTypeDefinition
98-
getDefinition :: Either NameError ObjectTypeDefinition
97+
getDefinition :: Either NameError Schema.ObjectTypeDefinition
9998

10099
class HasFieldDefinition a where
101-
getFieldDefinition :: Either NameError FieldDefinition
100+
getFieldDefinition :: Either NameError Schema.FieldDefinition
102101

103102

104103
-- Fields
105104
class HasFieldDefinitions a where
106-
getFieldDefinitions :: Either NameError [FieldDefinition]
105+
getFieldDefinitions :: Either NameError [Schema.FieldDefinition]
107106

108107
instance forall a as. (HasFieldDefinition a, HasFieldDefinitions as) => HasFieldDefinitions (a:as) where
109108
getFieldDefinitions = cons <$> getFieldDefinition @a <*> getFieldDefinitions @as
@@ -116,7 +115,7 @@ instance HasFieldDefinitions '[] where
116115
-- Union "Horse" '[Leg, Head, Tail]
117116
-- ^^^^^^^^^^^^^^^^^^ this part
118117
class UnionTypeObjectTypeDefinitionList a where
119-
getUnionTypeObjectTypeDefinitions :: Either NameError [ObjectTypeDefinition]
118+
getUnionTypeObjectTypeDefinitions :: Either NameError [Schema.ObjectTypeDefinition]
120119

121120
instance forall a as. (HasObjectDefinition a, UnionTypeObjectTypeDefinitionList as) => UnionTypeObjectTypeDefinitionList (a:as) where
122121
getUnionTypeObjectTypeDefinitions = cons <$> getDefinition @a <*> getUnionTypeObjectTypeDefinitions @as
@@ -126,7 +125,7 @@ instance UnionTypeObjectTypeDefinitionList '[] where
126125

127126
-- Interfaces
128127
class HasInterfaceDefinitions a where
129-
getInterfaceDefinitions :: Either NameError Interfaces
128+
getInterfaceDefinitions :: Either NameError Schema.Interfaces
130129

131130
instance forall a as. (HasInterfaceDefinition a, HasInterfaceDefinitions as) => HasInterfaceDefinitions (a:as) where
132131
getInterfaceDefinitions = cons <$> getInterfaceDefinition @a <*> getInterfaceDefinitions @as
@@ -135,35 +134,35 @@ instance HasInterfaceDefinitions '[] where
135134
getInterfaceDefinitions = pure []
136135

137136
class HasInterfaceDefinition a where
138-
getInterfaceDefinition :: Either NameError InterfaceTypeDefinition
137+
getInterfaceDefinition :: Either NameError Schema.InterfaceTypeDefinition
139138

140139
instance forall ks fields. (KnownSymbol ks, HasFieldDefinitions fields) => HasInterfaceDefinition (Interface ks fields) where
141140
getInterfaceDefinition =
142141
let name = nameFromSymbol @ks
143-
fields = NonEmptyList <$> getFieldDefinitions @fields
144-
in InterfaceTypeDefinition <$> name <*> fields
142+
fields = Schema.NonEmptyList <$> getFieldDefinitions @fields
143+
in Schema.InterfaceTypeDefinition <$> name <*> fields
145144

146145
-- Give users some help if they don't terminate Arguments with a Field:
147146
-- NB the "redundant constraints" warning is a GHC bug: https://ghc.haskell.org/trac/ghc/ticket/11099
148147
instance forall ks t. TypeError ('Text ":> Arguments must end with a Field") =>
149148
HasFieldDefinition (Argument ks t) where
150-
getFieldDefinition = notImplemented
149+
getFieldDefinition = panic ":> Arugments must end with a Field. This should not happen, but rather we'll get a compile-time error instead."
151150

152151
instance forall ks is ts. (KnownSymbol ks, HasInterfaceDefinitions is, HasFieldDefinitions ts) => HasAnnotatedType (Object ks is ts) where
153152
getAnnotatedType =
154153
let obj = getDefinition @(Object ks is ts)
155-
in (TypeNamed . DefinedType . TypeDefinitionObject) <$> obj
154+
in (Schema.TypeNamed . Schema.DefinedType . Schema.TypeDefinitionObject) <$> obj
156155

157156
instance forall t ks. (KnownSymbol ks, HasAnnotatedType t) => HasFieldDefinition (Field ks t) where
158157
getFieldDefinition =
159158
let name = nameFromSymbol @ks
160-
in FieldDefinition <$> name <*> pure [] <*> getAnnotatedType @t
159+
in Schema.FieldDefinition <$> name <*> pure [] <*> getAnnotatedType @t
161160

162161
class HasArgumentDefinition a where
163-
getArgumentDefinition :: Either NameError ArgumentDefinition
162+
getArgumentDefinition :: Either NameError Schema.ArgumentDefinition
164163

165164
instance forall ks t. (KnownSymbol ks, HasAnnotatedInputType t) => HasArgumentDefinition (Argument ks t) where
166-
getArgumentDefinition = ArgumentDefinition <$> argName <*> argType <*> defaultValue
165+
getArgumentDefinition = Schema.ArgumentDefinition <$> argName <*> argType <*> defaultValue
167166
where
168167
argName = nameFromSymbol @ks
169168
argType = getAnnotatedInputType @t
@@ -173,7 +172,7 @@ instance forall a b. (HasArgumentDefinition a, HasFieldDefinition b) => HasField
173172
getFieldDefinition =
174173
prependArg <$> argument <*> getFieldDefinition @b
175174
where
176-
prependArg arg (FieldDefinition name argDefs at) = FieldDefinition name (arg:argDefs) at
175+
prependArg arg (Schema.FieldDefinition name argDefs at) = Schema.FieldDefinition name (arg:argDefs) at
177176
argument = getArgumentDefinition @a
178177

179178
instance forall ks is fields.
@@ -182,8 +181,8 @@ instance forall ks is fields.
182181
getDefinition =
183182
let name = nameFromSymbol @ks
184183
interfaces = getInterfaceDefinitions @is
185-
fields = NonEmptyList <$> getFieldDefinitions @fields
186-
in ObjectTypeDefinition <$> name <*> interfaces <*> fields
184+
fields = Schema.NonEmptyList <$> getFieldDefinitions @fields
185+
in Schema.ObjectTypeDefinition <$> name <*> interfaces <*> fields
187186

188187
-- Builtin output types (annotated types)
189188
class HasAnnotatedType a where
@@ -192,21 +191,21 @@ class HasAnnotatedType a where
192191
-- forget this. Maybe we can flip the internal encoding to be
193192
-- non-null by default and needing explicit null-encoding (via
194193
-- Maybe).
195-
getAnnotatedType :: Either NameError (AnnotatedType GraphQL.Internal.Schema.Type)
194+
getAnnotatedType :: Either NameError (Schema.AnnotatedType Schema.GType)
196195

197196
-- | Turn a non-null type into the optional version of its own type.
198-
dropNonNull :: AnnotatedType t -> AnnotatedType t
199-
dropNonNull (TypeNonNull (NonNullTypeNamed t)) = TypeNamed t
200-
dropNonNull (TypeNonNull (NonNullTypeList t)) = TypeList t
201-
dropNonNull x@(TypeNamed _) = x
202-
dropNonNull x@(TypeList _) = x
197+
dropNonNull :: Schema.AnnotatedType t -> Schema.AnnotatedType t
198+
dropNonNull (Schema.TypeNonNull (Schema.NonNullTypeNamed t)) = Schema.TypeNamed t
199+
dropNonNull (Schema.TypeNonNull (Schema.NonNullTypeList t)) = Schema.TypeList t
200+
dropNonNull x@(Schema.TypeNamed _) = x
201+
dropNonNull x@(Schema.TypeList _) = x
203202

204203
instance forall a. HasAnnotatedType a => HasAnnotatedType (Maybe a) where
205204
-- see TODO in HasAnnotatedType class
206205
getAnnotatedType = dropNonNull <$> getAnnotatedType @a
207206

208-
builtinType :: Builtin -> Either NameError (AnnotatedType GraphQL.Internal.Schema.Type)
209-
builtinType = pure . TypeNonNull . NonNullTypeNamed . BuiltinType
207+
builtinType :: Schema.Builtin -> Either NameError (Schema.AnnotatedType Schema.GType)
208+
builtinType = pure . Schema.TypeNonNull . Schema.NonNullTypeNamed . Schema.BuiltinType
210209

211210
-- TODO(jml): Given that AnnotatedType is parametrised, we can probably reduce
212211
-- a great deal of duplication by making HasAnnotatedType a parametrised type
@@ -216,93 +215,93 @@ builtinType = pure . TypeNonNull . NonNullTypeNamed . BuiltinType
216215
-- than listing each individually.
217216

218217
instance HasAnnotatedType Int where
219-
getAnnotatedType = builtinType GInt
218+
getAnnotatedType = builtinType Schema.GInt
220219

221220
instance HasAnnotatedType Int32 where
222-
getAnnotatedType = builtinType GInt
221+
getAnnotatedType = builtinType Schema.GInt
223222

224223
instance HasAnnotatedType Bool where
225-
getAnnotatedType = builtinType GBool
224+
getAnnotatedType = builtinType Schema.GBool
226225

227226
instance HasAnnotatedType Text where
228-
getAnnotatedType = builtinType GString
227+
getAnnotatedType = builtinType Schema.GString
229228

230229
instance HasAnnotatedType Double where
231-
getAnnotatedType = builtinType GFloat
230+
getAnnotatedType = builtinType Schema.GFloat
232231

233232
instance HasAnnotatedType Float where
234-
getAnnotatedType = builtinType GFloat
233+
getAnnotatedType = builtinType Schema.GFloat
235234

236235
instance forall t. (HasAnnotatedType t) => HasAnnotatedType (List t) where
237-
getAnnotatedType = TypeList . ListType <$> getAnnotatedType @t
236+
getAnnotatedType = Schema.TypeList . Schema.ListType <$> getAnnotatedType @t
238237

239238
instance forall ks enum. (KnownSymbol ks, GraphQLEnum enum) => HasAnnotatedType (Enum ks enum) where
240239
getAnnotatedType = do
241240
let name = nameFromSymbol @ks
242-
let enums = sequenceA (enumValues @enum) :: Either NameError [Name]
243-
let et = EnumTypeDefinition <$> name <*> map (map EnumValueDefinition) enums
244-
TypeNonNull . NonNullTypeNamed . DefinedType . TypeDefinitionEnum <$> et
241+
let enums = sequenceA (enumValues @enum) :: Either NameError [Schema.Name]
242+
let et = Schema.EnumTypeDefinition <$> name <*> map (map Schema.EnumValueDefinition) enums
243+
Schema.TypeNonNull . Schema.NonNullTypeNamed . Schema.DefinedType . Schema.TypeDefinitionEnum <$> et
245244

246245
instance forall ks as. (KnownSymbol ks, UnionTypeObjectTypeDefinitionList as) => HasAnnotatedType (Union ks as) where
247246
getAnnotatedType =
248247
let name = nameFromSymbol @ks
249-
types = NonEmptyList <$> getUnionTypeObjectTypeDefinitions @as
250-
in (TypeNamed . DefinedType . TypeDefinitionUnion) <$> (UnionTypeDefinition <$> name <*> types)
248+
types = Schema.NonEmptyList <$> getUnionTypeObjectTypeDefinitions @as
249+
in (Schema.TypeNamed . Schema.DefinedType . Schema.TypeDefinitionUnion) <$> (Schema.UnionTypeDefinition <$> name <*> types)
251250

252251
-- Help users with better type errors
253252
instance TypeError ('Text "Cannot encode Integer because it has arbitrary size but the JSON encoding is a number") =>
254253
HasAnnotatedType Integer where
255-
getAnnotatedType = undefined
254+
getAnnotatedType = panic "Cannot encode Integer into JSON due to its arbitrary size. Should get a compile-time error instead of this."
256255

257256

258257
-- Builtin input types
259258
class HasAnnotatedInputType a where
260259
-- See TODO comment in "HasAnnotatedType" class for nullability.
261-
getAnnotatedInputType :: Either NameError (AnnotatedType InputType)
262-
default getAnnotatedInputType :: (Generic a, GenericAnnotatedInputType (Rep a)) => Either NameError (AnnotatedType InputType)
260+
getAnnotatedInputType :: Either NameError (Schema.AnnotatedType Schema.InputType)
261+
default getAnnotatedInputType :: (Generic a, GenericAnnotatedInputType (Rep a)) => Either NameError (Schema.AnnotatedType Schema.InputType)
263262
getAnnotatedInputType = genericGetAnnotatedInputType @(Rep a)
264263

265264
instance forall a. HasAnnotatedInputType a => HasAnnotatedInputType (Maybe a) where
266265
getAnnotatedInputType = dropNonNull <$> getAnnotatedInputType @a
267266

268-
builtinInputType :: Builtin -> Either NameError (AnnotatedType InputType)
269-
builtinInputType = pure . TypeNonNull . NonNullTypeNamed . BuiltinInputType
267+
builtinInputType :: Schema.Builtin -> Either NameError (Schema.AnnotatedType Schema.InputType)
268+
builtinInputType = pure . Schema.TypeNonNull . Schema.NonNullTypeNamed . Schema.BuiltinInputType
270269

271270
instance HasAnnotatedInputType Int where
272-
getAnnotatedInputType = builtinInputType GInt
271+
getAnnotatedInputType = builtinInputType Schema.GInt
273272

274273
instance HasAnnotatedInputType Int32 where
275-
getAnnotatedInputType = builtinInputType GInt
274+
getAnnotatedInputType = builtinInputType Schema.GInt
276275

277276
instance HasAnnotatedInputType Bool where
278-
getAnnotatedInputType = builtinInputType GBool
277+
getAnnotatedInputType = builtinInputType Schema.GBool
279278

280279
instance HasAnnotatedInputType Text where
281-
getAnnotatedInputType = builtinInputType GString
280+
getAnnotatedInputType = builtinInputType Schema.GString
282281

283282
instance HasAnnotatedInputType Double where
284-
getAnnotatedInputType = builtinInputType GFloat
283+
getAnnotatedInputType = builtinInputType Schema.GFloat
285284

286285
instance HasAnnotatedInputType Float where
287-
getAnnotatedInputType = builtinInputType GFloat
286+
getAnnotatedInputType = builtinInputType Schema.GFloat
288287

289288
instance forall t. (HasAnnotatedInputType t) => HasAnnotatedInputType (List t) where
290-
getAnnotatedInputType = TypeList . ListType <$> getAnnotatedInputType @t
289+
getAnnotatedInputType = Schema.TypeList . Schema.ListType <$> getAnnotatedInputType @t
291290

292291
instance forall ks enum. (KnownSymbol ks, GraphQLEnum enum) => HasAnnotatedInputType (Enum ks enum) where
293292
getAnnotatedInputType = do
294293
let name = nameFromSymbol @ks
295-
enums = sequenceA (enumValues @enum) :: Either NameError [Name]
296-
let et = EnumTypeDefinition <$> name <*> map (map EnumValueDefinition) enums
297-
TypeNonNull . NonNullTypeNamed . DefinedInputType . InputTypeDefinitionEnum <$> et
294+
enums = sequenceA (enumValues @enum) :: Either NameError [Schema.Name]
295+
let et = Schema.EnumTypeDefinition <$> name <*> map (map Schema.EnumValueDefinition) enums
296+
Schema.TypeNonNull . Schema.NonNullTypeNamed . Schema.DefinedInputType . Schema.InputTypeDefinitionEnum <$> et
298297

299298

300299
-- Generic getAnnotatedInputType function
301300
class GenericAnnotatedInputType (f :: Type -> Type) where
302-
genericGetAnnotatedInputType :: Either NameError (AnnotatedType InputType)
301+
genericGetAnnotatedInputType :: Either NameError (Schema.AnnotatedType Schema.InputType)
303302

304303
class GenericInputObjectFieldDefinitions (f :: Type -> Type) where
305-
genericGetInputObjectFieldDefinitions :: Either NameError [InputObjectFieldDefinition]
304+
genericGetInputObjectFieldDefinitions :: Either NameError [Schema.InputObjectFieldDefinition]
306305

307306
instance forall dataName consName records s l p.
308307
( KnownSymbol dataName
@@ -313,12 +312,12 @@ instance forall dataName consName records s l p.
313312
)) where
314313
genericGetAnnotatedInputType = do
315314
name <- nameFromSymbol @dataName
316-
map ( TypeNonNull
317-
. NonNullTypeNamed
318-
. DefinedInputType
319-
. InputTypeDefinitionObject
320-
. (InputObjectTypeDefinition name)
321-
. NonEmptyList
315+
map ( Schema.TypeNonNull
316+
. Schema.NonNullTypeNamed
317+
. Schema.DefinedInputType
318+
. Schema.InputTypeDefinitionObject
319+
. (Schema.InputObjectTypeDefinition name)
320+
. Schema.NonEmptyList
322321
) (genericGetInputObjectFieldDefinitions @records)
323322

324323
instance forall wrappedType fieldName rest u s l.
@@ -329,7 +328,7 @@ instance forall wrappedType fieldName rest u s l.
329328
genericGetInputObjectFieldDefinitions = do
330329
name <- nameFromSymbol @fieldName
331330
annotatedInputType <- getAnnotatedInputType @wrappedType
332-
let l = InputObjectFieldDefinition name annotatedInputType Nothing
331+
let l = Schema.InputObjectFieldDefinition name annotatedInputType Nothing
333332
r <- genericGetInputObjectFieldDefinitions @rest
334333
pure (l:r)
335334

@@ -340,5 +339,5 @@ instance forall wrappedType fieldName u s l.
340339
genericGetInputObjectFieldDefinitions = do
341340
name <- nameFromSymbol @fieldName
342341
annotatedInputType <- getAnnotatedInputType @wrappedType
343-
let l = InputObjectFieldDefinition name annotatedInputType Nothing
342+
let l = Schema.InputObjectFieldDefinition name annotatedInputType Nothing
344343
pure [l]

src/GraphQL/API/Enum.hs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,20 @@ instance forall conName p b sa sb.
8686
( TypeError ('Text "Constructor not unary: " ':<>: 'Text conName)
8787
, KnownSymbol conName
8888
) => GenericEnumValues (C1 ('MetaCons conName p b) (S1 sa sb)) where
89-
genericEnumValues = undefined
90-
genericEnumFromValue = undefined
91-
genericEnumToValue = undefined
89+
genericEnumValues = nonUnaryConstructorError
90+
genericEnumFromValue = nonUnaryConstructorError
91+
genericEnumToValue = nonUnaryConstructorError
9292

9393
instance forall conName p b sa sb f.
9494
( TypeError ('Text "Constructor not unary: " ':<>: 'Text conName)
9595
, KnownSymbol conName
9696
) => GenericEnumValues (C1 ('MetaCons conName p b) (S1 sa sb) :+: f) where
97-
genericEnumValues = undefined
98-
genericEnumFromValue = undefined
99-
genericEnumToValue = undefined
97+
genericEnumValues = nonUnaryConstructorError
98+
genericEnumFromValue = nonUnaryConstructorError
99+
genericEnumToValue = nonUnaryConstructorError
100100

101+
nonUnaryConstructorError :: a
102+
nonUnaryConstructorError = panic "Tried to construct enum with non-unary constructor. Should get a compile-time error instead of this."
101103

102104
-- | For each enum type we need 1) a list of all possible values 2) a
103105
-- way to serialise and 3) deserialise.

src/GraphQL/Internal/Execution.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import GraphQL.Internal.Validation
3232
, VariableDefinition(..)
3333
, VariableValue
3434
, Variable
35-
, Type(..)
35+
, GType(..)
3636
)
3737

3838
-- | Get an operation from a GraphQL document

src/GraphQL/Internal/Schema.hs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
--
99
-- Equivalent representation of GraphQL /values/ is in "GraphQL.Value".
1010
module GraphQL.Internal.Schema
11-
( Type(..)
11+
( GType(..)
1212
-- * Builtin types
1313
, Builtin(..)
1414
-- * Defining new types
@@ -40,7 +40,7 @@ module GraphQL.Internal.Schema
4040
, lookupType
4141
) where
4242

43-
import Protolude hiding (Type)
43+
import Protolude
4444

4545
import qualified Data.Map as Map
4646
import GraphQL.Value (Value)
@@ -100,13 +100,13 @@ data NonNullType t = NonNullTypeNamed t
100100
| NonNullTypeList (ListType t)
101101
deriving (Eq, Ord, Show)
102102

103-
data Type = DefinedType TypeDefinition | BuiltinType Builtin deriving (Eq, Ord, Show)
103+
data GType = DefinedType TypeDefinition | BuiltinType Builtin deriving (Eq, Ord, Show)
104104

105-
instance DefinesTypes Type where
105+
instance DefinesTypes GType where
106106
getDefinedTypes (BuiltinType _) = mempty
107107
getDefinedTypes (DefinedType t) = getDefinedTypes t
108108

109-
instance HasName Type where
109+
instance HasName GType where
110110
getName (DefinedType x) = getName x
111111
getName (BuiltinType x) = getName x
112112

@@ -154,7 +154,7 @@ instance DefinesTypes ObjectTypeDefinition where
154154

155155
type Interfaces = [InterfaceTypeDefinition]
156156

157-
data FieldDefinition = FieldDefinition Name [ArgumentDefinition] (AnnotatedType Type)
157+
data FieldDefinition = FieldDefinition Name [ArgumentDefinition] (AnnotatedType GType)
158158
deriving (Eq, Ord, Show)
159159

160160
instance HasName FieldDefinition where

0 commit comments

Comments
 (0)