Skip to content

Commit

Permalink
Formatter pass
Browse files Browse the repository at this point in the history
  • Loading branch information
onno-vos-dev committed Mar 28, 2024
1 parent 643d443 commit 70fdc8e
Show file tree
Hide file tree
Showing 11 changed files with 1,148 additions and 152 deletions.
13 changes: 10 additions & 3 deletions lib/aws_codegen.ex
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,17 @@ defmodule AWS.CodeGen do
template_path = Path.join(template_base_path, template)

context = protocol_service.load_context(language, spec, endpoints_spec)

case Map.get(context, :actions) do
[] ->
IO.puts(["Skipping ", spec.module_name, " due to no actions"])

_ ->
code = render(context, template_path)

IO.puts(["Writing ", spec.module_name, " to ", output_path])
IO.puts(["Writing ", spec.module_name, " to ", output_path])

File.write(output_path, code)
File.write(output_path, code)
end
else
IO.puts("Failed to generate #{spec.module_name}, protocol #{spec.protocol}")
Expand Down Expand Up @@ -150,7 +152,12 @@ defmodule AWS.CodeGen do
end

defp get_endpoints_spec(base_path) do
Path.join([base_path, "../../", "smithy-aws-go-codegen/src/main/resources/software/amazon/smithy/aws/go/codegen", "endpoints.json"])
Path.join([
base_path,
"../../",
"smithy-aws-go-codegen/src/main/resources/software/amazon/smithy/aws/go/codegen",
"endpoints.json"
])
|> Spec.parse_json()
|> get_in(["partitions"])
|> Enum.filter(fn x -> x["partition"] == "aws" end)
Expand Down
9 changes: 6 additions & 3 deletions lib/aws_codegen/docstring.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ defmodule AWS.CodeGen.Docstring do
|> String.trim_trailing()
|> String.replace(@two_break_lines, "\n%%\n")
|> String.replace(~r/'/, "'")
|> String.replace("`AVAILABLE`", "`AVAILABLE'") # aws-sdk-go docs are broken for this, hack it to make the edocs work
|> String.replace("`PENDING`", "`PENDING'") # aws-sdk-go docs are broken for this, hack it to make the edocs work
# aws-sdk-go docs are broken for this, hack it to make the edocs work
|> String.replace("`AVAILABLE`", "`AVAILABLE'")
# aws-sdk-go docs are broken for this, hack it to make the edocs work
|> String.replace("`PENDING`", "`PENDING'")
end

defp split_first_sentence_in_one_line(doc) do
Expand Down Expand Up @@ -292,6 +294,7 @@ defmodule AWS.CodeGen.Docstring do
case Enum.find(attrs, fn {attr, _} -> attr == "href" end) do
{_, href} ->
text = Floki.text(children)

if text == href do
"[#{href}]"
else
Expand All @@ -304,7 +307,7 @@ defmodule AWS.CodeGen.Docstring do

{_, _attrs, children} ->
"#{Floki.text(children)}"
end)
end)
|> Floki.raw_html(encode: true)
end

Expand Down
28 changes: 23 additions & 5 deletions lib/aws_codegen/post_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,23 @@ defmodule AWS.CodeGen.PostService do
traits = service["traits"]
actions = collect_actions(language, spec.api)
shapes = Shapes.collect_shapes(language, spec.api)
endpoint_prefix = traits["aws.api#service"]["endpointPrefix"] || traits["aws.api#service"]["arnNamespace"]

endpoint_prefix =
traits["aws.api#service"]["endpointPrefix"] || traits["aws.api#service"]["arnNamespace"]

endpoint_info = endpoints_spec["services"][endpoint_prefix]
is_global = not is_nil(endpoint_info) and not Map.get(endpoint_info, "isRegionalized", true)

credential_scope =
if is_global do
endpoint_info["endpoints"]["aws-global"]["credentialScope"]["region"]
end

json_version = AWS.CodeGen.Util.get_json_version(service)
protocol = spec.protocol |> to_string()
content_type = @configuration[protocol][:content_type]
content_type = content_type <> if protocol == "json", do: json_version, else: ""

signing_name =
if String.starts_with?(endpoint_prefix, "api.") do
String.replace(endpoint_prefix, "api.", "")
Expand Down Expand Up @@ -108,7 +114,9 @@ defmodule AWS.CodeGen.PostService do
|> case do
{key, _} ->
String.replace(key, ~r/.*#/, "")
nil -> nil

nil ->
nil
end
end

Expand All @@ -119,12 +127,22 @@ defmodule AWS.CodeGen.PostService do
Enum.reduce(shapes, [], fn {_, shape}, acc ->
case shape["type"] do
"service" ->

[acc | List.wrap(shape["operations"])]

"resource" ->
[shape["operations"], shape["collectionOperations"], shape["create"], shape["put"], shape["read"], shape["update"], shape["delete"], shape["list"]]
[
shape["operations"],
shape["collectionOperations"],
shape["create"],
shape["put"],
shape["read"],
shape["update"],
shape["delete"],
shape["list"]
]
|> Enum.reject(&is_nil/1)
|> Kernel.++(acc)

_ ->
acc
end
Expand All @@ -134,6 +152,7 @@ defmodule AWS.CodeGen.PostService do

Enum.map(operations, fn operation ->
operation_spec = shapes[operation]

%Action{
arity: 3,
docstring:
Expand All @@ -152,5 +171,4 @@ defmodule AWS.CodeGen.PostService do
|> Enum.sort(fn a, b -> a.function_name < b.function_name end)
|> Enum.uniq()
end

end
41 changes: 33 additions & 8 deletions lib/aws_codegen/rest_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ defmodule AWS.CodeGen.RestService do
traits = service["traits"]
actions = collect_actions(language, spec.api)
protocol = spec.protocol
endpoint_prefix = traits["aws.api#service"]["endpointPrefix"] || traits["aws.api#service"]["arnNamespace"] ##TODO: for some reason this field is not always present and docs are not clear on what to do
## TODO: for some reason this field is not always present and docs are not clear on what to do
endpoint_prefix =
traits["aws.api#service"]["endpointPrefix"] || traits["aws.api#service"]["arnNamespace"]

endpoint_info = endpoints_spec["services"][endpoint_prefix]
is_global = not is_nil(endpoint_info) and not Map.get(endpoint_info, "isRegionalized", true)

Expand Down Expand Up @@ -148,7 +151,8 @@ defmodule AWS.CodeGen.RestService do
signing_name: signing_name,
signature_version: AWS.CodeGen.Util.get_signature_version(service),
service_id: AWS.CodeGen.Util.get_service_id(service),
target_prefix: nil, ##TODO: metadata["targetPrefix"],
## TODO: metadata["targetPrefix"],
target_prefix: nil,
shapes: Shapes.collect_shapes(language, spec.api)
}
end
Expand All @@ -167,6 +171,7 @@ defmodule AWS.CodeGen.RestService do
"""
def function_parameters(action, required_only \\ false) do
language = action.language

Enum.join([
join_parameters(action.url_parameters, language)
| case action.method do
Expand Down Expand Up @@ -214,12 +219,22 @@ defmodule AWS.CodeGen.RestService do
Enum.reduce(shapes, [], fn {_, shape}, acc ->
case shape["type"] do
"service" ->

List.wrap(shape["operations"]) ++ acc

"resource" ->
[shape["operations"], shape["collectionOperations"], shape["create"], shape["put"], shape["read"], shape["update"], shape["delete"], shape["list"]]
[
shape["operations"],
shape["collectionOperations"],
shape["create"],
shape["put"],
shape["read"],
shape["update"],
shape["delete"],
shape["list"]
]
|> Enum.reject(&is_nil/1)
|> Kernel.++(acc)

_ ->
acc
end
Expand Down Expand Up @@ -257,6 +272,7 @@ defmodule AWS.CodeGen.RestService do

input_shape = Shapes.get_input_shape(operation_spec)
output_shape = Shapes.get_output_shape(operation_spec)

%Action{
arity: length(url_parameters) + len_for_method,
docstring:
Expand Down Expand Up @@ -298,12 +314,16 @@ defmodule AWS.CodeGen.RestService do
end

defp collect_url_parameters(language, api_spec, operation) do
url_params = collect_parameters(language, api_spec, operation, "input", "smithy.api#httpLabel")
url_params =
collect_parameters(language, api_spec, operation, "input", "smithy.api#httpLabel")

url_params
end

defp collect_query_parameters(language, api_spec, operation) do
query_params = collect_parameters(language, api_spec, operation, "input", "smithy.api#httpQueryParams")
query_params =
collect_parameters(language, api_spec, operation, "input", "smithy.api#httpQueryParams")

params = collect_parameters(language, api_spec, operation, "input", "smithy.api#httpQuery")
query_params ++ params
end
Expand All @@ -318,13 +338,18 @@ defmodule AWS.CodeGen.RestService do

defp collect_parameters(language, api_spec, operation, data_type, param_type) do
shape_name = api_spec["shapes"][operation][data_type]["target"]

if shape_name do
case api_spec["shapes"][shape_name] do
nil ->
[]

shape ->
required_members =
for {name, %{"traits" => traits}} <- shape["members"], Map.has_key?(traits, "smithy.api#required"), do: name
for {name, %{"traits" => traits}} <- shape["members"],
Map.has_key?(traits, "smithy.api#required"),
do: name

shape["members"]
|> Enum.filter(filter_fn(param_type))
|> Enum.map(fn {name, x} ->
Expand Down Expand Up @@ -356,6 +381,7 @@ defmodule AWS.CodeGen.RestService do
required: required
}
end

defp build_parameter(language, {name, data}, required) do
%Parameter{
code_name:
Expand All @@ -369,5 +395,4 @@ defmodule AWS.CodeGen.RestService do
required: required
}
end

end
17 changes: 8 additions & 9 deletions lib/aws_codegen/shapes.ex
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
defmodule AWS.CodeGen.Shapes do

defmodule Shape do
defstruct name: nil,
type: nil,
members: [],
member: [],
enum: [],
min: nil,
required: [],
is_input: nil
type: nil,
members: [],
member: [],
enum: [],
min: nil,
required: [],
is_input: nil
end

def get_input_shape(operation_spec) do
Expand Down Expand Up @@ -39,6 +38,7 @@ defmodule AWS.CodeGen.Shapes do
## TODO: Should we validate or search for trait `smithy.api#httpPayload` rather than
## trust that the member is always named `Body`?
inner_spec = get_in(shapes, [shape, "members", "Body"])

if is_map(inner_spec) && Map.has_key?(inner_spec, "target") do
## TODO: we should extract the type from the actual shape `type` rather than infer it from the naming
inner_spec["target"]
Expand All @@ -52,5 +52,4 @@ defmodule AWS.CodeGen.Shapes do
def is_input?(shape) do
!Map.has_key?(shape, "traits") or Map.has_key?(shape["traits"], "smithy.api#input")
end

end
51 changes: 29 additions & 22 deletions lib/aws_codegen/spec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,44 @@ defmodule AWS.CodeGen.Spec do
shape_name: nil

def parse(api_filename, language) do
api_name = api_filename
|> Path.basename()
|> String.replace(["-", ".json"], "")
api_name =
api_filename
|> Path.basename()
|> String.replace(["-", ".json"], "")

api = parse_json(api_filename)

service_name =
api
|> find_service()
|> String.replace("com.amazonaws.#{api_name}#", "")

traits = api["shapes"]["com.amazonaws." <> api_name <> "#" <> service_name]["traits"]

protocol = Enum.find_value(traits, fn {k, _v} ->
case String.split(k, "#") do
["aws.protocols", protocol] -> protocol
_ -> nil
end
end)
|> String.replace("restJson1", "rest_json")
|> String.replace(["awsJson1_0", "awsJson1_1"], "json")
|> String.replace("awsQuery", "query")
|> String.replace("restXml", "rest_xml")
|> String.replace("ec2Query", "ec2")
|> then(fn value->
if value in ~w(rest_json json query rest_xml ec2) do
value
else
raise "the protocol #{value} is not valid"
end
end)
|> String.to_atom()
protocol =
Enum.find_value(traits, fn {k, _v} ->
case String.split(k, "#") do
["aws.protocols", protocol] -> protocol
_ -> nil
end
end)
|> String.replace("restJson1", "rest_json")
|> String.replace(["awsJson1_0", "awsJson1_1"], "json")
|> String.replace("awsQuery", "query")
|> String.replace("restXml", "rest_xml")
|> String.replace("ec2Query", "ec2")
|> then(fn value ->
if value in ~w(rest_json json query rest_xml ec2) do
value
else
raise "the protocol #{value} is not valid"
end
end)
|> String.to_atom()

module_name = module_name(traits, language)
filename = filename(module_name, language)

%AWS.CodeGen.Spec{
protocol: protocol,
module_name: module_name,
Expand Down
Loading

0 comments on commit 70fdc8e

Please sign in to comment.