api-tools-0.4: DSL for generating API boilerplate and docs

Safe HaskellNone

Data.API.NormalForm

Contents

Description

This module defines a normalised representation of APIs, used for comparing them in the migrations changelog, and to analyse dependencies.

Synopsis

Normalised API types

type NormAPI = Map TypeName NormTypeDeclSource

The API type has too much extra info for us to be able to simply compare them with (==). Our strategy is to strip out ancillary information and normalise into a canonical form, and then we can use a simple (==) compare.

Our normalised API discards most of the details of each type, keeping just essential information about each type. We discard order of types and fields, so we can use just associative maps.

data NormTypeDecl Source

The normal or canonical form for a type declaration, an APINode. Equality of the normal form indicates equivalence of APIs.

We track all types.

type NormRecordType = Map FieldName APITypeSource

The canonical form of a record type is a map from fields to values...

type NormUnionType = Map FieldName APITypeSource

...similarly a union is a map from fields to alternatives...

type NormEnumType = Set FieldNameSource

...and an enum is a set of values.

Converting to normal form

apiNormalForm :: API -> NormAPISource

Compute the normal form of an API, discarding extraneous information.

declNF :: Spec -> NormTypeDeclSource

Compute the normal form of a single type declaration.

Dependency analysis

typeDeclsFreeVars :: NormAPI -> Set TypeNameSource

Find the set of type names used in an API

typeDeclFreeVars :: NormTypeDecl -> Set TypeNameSource

Find the set of type names used in a declaration

typeFreeVars :: APIType -> Set TypeNameSource

Find the set of type names used in an type

typeDeclaredInApi :: TypeName -> NormAPI -> BoolSource

Check if a type is declared in the API

typeUsedInApi :: TypeName -> NormAPI -> BoolSource

Check if a type is used anywhere in the API

typeUsedInTransitiveDep :: TypeName -> TypeName -> NormAPI -> BoolSource

Check if the first type's transitive dependencies include the second type

transitiveDeps :: NormAPI -> Set TypeName -> Set TypeNameSource

Compute the transitive dependencies of a set of types

transitiveReverseDeps :: NormAPI -> Set TypeName -> Set TypeNameSource

Compute the set of types that depend (transitively) on the given types

Invariant validation

apiInvariant :: NormAPI -> Either (Set TypeName) ()Source

Test that all the types used in the API are declared. If not, return the set of undeclared types.

declIsValid :: NormTypeDecl -> NormAPI -> Either (Set TypeName) ()Source

Test that all the types used in a type declaration are declared in the API. If not, return the set of undeclared types.

typeIsValid :: APIType -> NormAPI -> Either (Set TypeName) ()Source

Test that all the free type names in a type are declared in the API. If not, return the set of undeclared types.

Modifying types

substTypeDecl :: (TypeName -> APIType) -> NormTypeDecl -> NormTypeDeclSource

Substitute types for type names in a declaration

substType :: (TypeName -> APIType) -> APIType -> APITypeSource

Substitute types for type names in a type

renameTypeUses :: TypeName -> TypeName -> NormAPI -> NormAPISource

Rename the first type to the second throughout the API