Skip to content

Commit

Permalink
Qualified references (#43)
Browse files Browse the repository at this point in the history
Closes #39 by adding fully qualified names in the generated Elm code when referencing definitions from other modules.

* Adds 'module' to schema definitions,
* passes the schema definition context - instead of the type dictionary - to each printer function,
* uses fully qualified names when referencing types, encoders and decoders
  from other modules in the generated Elm code,
* removes the explicit import of types, decoders and encoders from other modules in the generated Elm code. Now just import the module and nothing else,
* adds support for the 'title' property in the schema root object,
* removes some code redundancy, and
* updates readme with new elm output.
  • Loading branch information
dragonwasrobot authored Aug 8, 2017
1 parent bbbd5a2 commit 28a7c55
Show file tree
Hide file tree
Showing 32 changed files with 822 additions and 759 deletions.
80 changes: 70 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,7 @@ module Domain.Definitions exposing (..)

import Json.Decode as Decode
exposing
( float
, int
, string
, list
, succeed
( succeed
, fail
, map
, maybe
Expand All @@ -95,10 +91,6 @@ import Json.Decode.Pipeline
import Json.Encode as Encode
exposing
( Value
, float
, int
, string
, list
, object
)

Expand Down Expand Up @@ -198,10 +190,78 @@ that have references across files, e.g.
}
```

then the corresponding Elm file, `Domain.Circle`, will import the
then the corresponding Elm file, `Domain/Circle.elm`, will import the
definitions (types, encoders and decoders) from the other Elm module,
`Domain/Definitions.elm`.

``` elm
module Domain.Circle exposing (..)

-- Schema for a circle shape

import Json.Decode as Decode
exposing
( succeed
, fail
, map
, maybe
, field
, at
, andThen
, oneOf
, nullable
, Decoder
)
import Json.Decode.Pipeline
exposing
( decode
, required
, optional
, custom
)
import Json.Encode as Encode
exposing
( Value
, object
)
import Domain.Definitions


type alias Circle =
{ center : Domain.Definitions.Point
, color : Maybe Domain.Definitions.Color
, radius : Float
}


circleDecoder : Decoder Circle
circleDecoder =
decode Circle
|> required "center" Domain.Definitions.pointDecoder
|> optional "color" (Decode.string |> andThen Domain.Definitions.colorDecoder |> maybe) Nothing
|> required "radius" Decode.float


encodeCircle : Circle -> Value
encodeCircle circle =
let
center =
[ ( "center", Domain.Definitions.encodePoint circle.center ) ]

color =
case circle.color of
Just color ->
[ ( "color", Domain.Definitions.encodeColor color ) ]

Nothing ->
[]

radius =
[ ( "radius", Encode.float circle.radius ) ]
in
object <| center ++ color ++ radius
```

## Tests

Run the standard mix task
Expand Down
51 changes: 19 additions & 32 deletions examples/example-output-elm-code/Domain/Circle.elm
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ module Domain.Circle exposing (..)

import Json.Decode as Decode
exposing
( float
, int
, string
, list
, succeed
( succeed
, fail
, map
, maybe
Expand All @@ -29,53 +25,44 @@ import Json.Decode.Pipeline
import Json.Encode as Encode
exposing
( Value
, float
, int
, string
, list
, object
)
import Domain.Definitions
exposing
( Color
, colorDecoder
, encodeColor
, Point
, pointDecoder
, encodePoint
)


type alias Root =
{ center : Point
, color : Maybe Color
type alias Circle =
{ center : Domain.Definitions.Point
, color : Maybe Domain.Definitions.Color
, radius : Float
}


rootDecoder : Decoder Root
rootDecoder =
decode Root
|> required "center" pointDecoder
|> optional "color" (Decode.string |> andThen colorDecoder |> maybe) Nothing
circleDecoder : Decoder Circle
circleDecoder =
decode Circle
|> required "center" Domain.Definitions.pointDecoder
|> optional "color" (Decode.string |> andThen Domain.Definitions.colorDecoder |> maybe) Nothing
|> required "radius" Decode.float


encodeRoot : Root -> Value
encodeRoot root =
encodeCircle : Circle -> Value
encodeCircle circle =
let
center =
[ ( "center", encodePoint root.center ) ]
[ ( "center", Domain.Definitions.encodePoint circle.center ) ]

color =
case root.color of
case circle.color of
Just color ->
[ ( "color", encodeColor color ) ]
[ ( "color", Domain.Definitions.encodeColor color ) ]

Nothing ->
[]

radius =
[ ( "radius", Encode.float root.radius ) ]
[ ( "radius", Encode.float circle.radius ) ]
in
object <| center ++ color ++ radius
object <|
center
++ color
++ radius
13 changes: 3 additions & 10 deletions examples/example-output-elm-code/Domain/Definitions.elm
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ module Domain.Definitions exposing (..)

import Json.Decode as Decode
exposing
( float
, int
, string
, list
, succeed
( succeed
, fail
, map
, maybe
Expand All @@ -29,10 +25,6 @@ import Json.Decode.Pipeline
import Json.Encode as Encode
exposing
( Value
, float
, int
, string
, list
, object
)

Expand Down Expand Up @@ -101,4 +93,5 @@ encodePoint point =
y =
[ ( "y", Encode.float point.y ) ]
in
object <| x ++ y
object <|
x ++ y
4 changes: 2 additions & 2 deletions lib/js2e.ex
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ defmodule JS2E do
@spec generate([String.t], String.t) :: :ok
def generate(json_schema_paths, module_name) do

schema_dict = Parser.parse_schema_files(json_schema_paths)
printed_schemas = Printer.print_schemas(schema_dict, module_name)
schema_dict = Parser.parse_schema_files(json_schema_paths, module_name)
printed_schemas = Printer.print_schemas(schema_dict)

printed_schemas
|> Enum.each(fn{file_path, file_content} ->
Expand Down
18 changes: 9 additions & 9 deletions lib/parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,27 @@ defmodule JS2E.Parser do
"http://json-schema.org/draft-04/schema"
]

@spec parse_schema_files([String.t]) :: Types.schemaDictionary
def parse_schema_files(json_schema_paths) do
@spec parse_schema_files([String.t], String.t) :: Types.schemaDictionary
def parse_schema_files(json_schema_paths, module_name) do
json_schema_paths
|> Enum.reduce(%{}, fn (json_schema_path, schema_dict) ->

json_schema_path
|> parse_schema_file
|> parse_schema_file(module_name)
|> Map.merge(schema_dict)
end)
end

@spec parse_schema_file(String.t) :: Types.schemaDictionary
def parse_schema_file(json_schema_path) do
@spec parse_schema_file(String.t, String.t) :: Types.schemaDictionary
def parse_schema_file(json_schema_path, module_name) do
json_schema_path
|> File.read!
|> Poison.decode!
|> parse_schema
|> parse_schema(module_name)
end

@spec parse_schema(map) :: Types.schemaDictionary
def parse_schema(schema_root_node) do
@spec parse_schema(map, String.t) :: Types.schemaDictionary
def parse_schema(schema_root_node, module_name) do

if not supported_schema_version?(schema_root_node) do
exit(:bad_version)
Expand All @@ -64,7 +64,7 @@ defmodule JS2E.Parser do
|> Map.merge(root, handle_conflict)

%{to_string(schema_id) =>
SchemaDefinition.new(schema_id, title, description, types)}
SchemaDefinition.new(schema_id, title, module_name, description, types)}
end

@spec parse_schema_id(any) :: {:ok, URI.t} | {:error, String.t}
Expand Down
Loading

0 comments on commit 28a7c55

Please sign in to comment.