Skip to content

Commit

Permalink
Merge pull request #342 from higherkindness/sbt-mu-srcgen-#93
Browse files Browse the repository at this point in the history
Stop setting `methodNameStyle = Capitalize` when useIdiomaticEndpoints is true
  • Loading branch information
L-Lavigne committed Oct 9, 2020
2 parents dcdc26b + 07e25fa commit 7e4498b
Show file tree
Hide file tree
Showing 25 changed files with 292 additions and 249 deletions.
16 changes: 13 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
[comment]: <> (Don't edit this file!)
[comment]: <> (It is automatically updated after every release of https://github.com/47degrees/.github)
[comment]: <> (If you want to suggest a change, please open a PR or issue in that repository)

[![codecov.io](http://codecov.io/gh/higherkindness/skeuomorph/branch/master/graph/badge.svg)](http://codecov.io/gh/higherkindness/skeuomorph) [![Maven Central](https://img.shields.io/badge/maven%20central-0.0.22-green.svg)](https://oss.sonatype.org/#nexus-search;gav~io.higherkindness~skeuomorph*) [![Latest version](https://img.shields.io/badge/skeuomorph-0.0.22-green.svg)](https://index.scala-lang.org/higherkindness/skeuomorph) [![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://raw.githubusercontent.com/higherkindness/skeuomorph/master/LICENSE) [![Join the chat at https://gitter.im/higherkindness/skeuomorph](https://badges.gitter.im/higherkindness/skeuomorph.svg)](https://gitter.im/higherkindness/skeuomorph?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![GitHub Issues](https://img.shields.io/github/issues/higherkindness/skeuomorph.svg)](https://github.com/higherkindness/skeuomorph/issues)
[![codecov.io](http://codecov.io/gh/higherkindness/skeuomorph/branch/master/graph/badge.svg)](http://codecov.io/gh/higherkindness/skeuomorph)
[![Maven Central](https://img.shields.io/badge/maven%20central-0.0.25-green.svg)](https://oss.sonatype.org/#nexus-search;gav~io.higherkindness~skeuomorph*)
[![Latest version](https://img.shields.io/badge/skeuomorph-0.0.25-green.svg)](https://index.scala-lang.org/higherkindness/skeuomorph)
[![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://raw.githubusercontent.com/higherkindness/skeuomorph/master/LICENSE)
[![Join the chat at https://gitter.im/higherkindness/skeuomorph](https://badges.gitter.im/higherkindness/skeuomorph.svg)](https://gitter.im/higherkindness/skeuomorph?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![GitHub Issues](https://img.shields.io/github/issues/higherkindness/skeuomorph.svg)](https://github.com/higherkindness/skeuomorph/issues)

# @NAME@

Expand All @@ -18,15 +26,17 @@ More information can be found at the [microsite][].

For installing this library, add the following line to your `build.sbt` file:

```scala
```sbt
libraryDependencies += "io.higherkindness" %% "skeuomorph" % "@VERSION@"
```

The full documentation is available at the [skeuomorph](https://higherkindness.io/skeuomorph/) site.

## NOTICE

The following files `api-with-examples.yaml`, `petstore-expanded.yaml`, `callback-example.yaml`, `petstore.yaml`, `link-example.yaml` and `uspto.yaml` inside the folder (`test/resources/openapi/yaml`) were copied from [**OpenAPI Specification**](https://github.com/OAI/OpenAPI-Specification/) project under the terms of the licence [*Apache License Version 2.0, January 2004*](https://github.com/OAI/OpenAPI-Specification/blob/master/LICENSE).
The following files `api-with-examples.yaml`, `petstore-expanded.yaml`, `callback-example.yaml`, `petstore.yaml`, `link-example.yaml` and `uspto.yaml`
inside the folder (`test/resources/openapi/yaml`) were copied from [**OpenAPI Specification**](https://github.com/OAI/OpenAPI-Specification/)
project under the terms of the licence [*Apache License Version 2.0, January 2004*](https://github.com/OAI/OpenAPI-Specification/blob/master/LICENSE).

## Skeuomorph in the wild

Expand Down
13 changes: 4 additions & 9 deletions microsite/docs/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ title: Intro
permalink: docs/
---


# Skeuomorph

Skeuomorph is a library for transforming different schemas in Scala.
Expand Down Expand Up @@ -32,7 +31,7 @@ example. Or to a mu service description.

You can install skeuomorph as follows:

```scala
```sbt
libraryDependencies += "io.higherkindness" %% "skeuomorph" % "@VERSION@"
```

Expand Down Expand Up @@ -102,11 +101,9 @@ println("=====")
It would generate the following output:

```scala mdoc:passthrough
println("```scala")
(toMuSchema >>> println)(avroSchema)
println("=====")
(toMuSchema >>> printSchemaAsScala >>> println)(avroSchema)
println("```")
```

## Protobuf
Expand All @@ -117,8 +114,9 @@ Given the proto file below:

_user.proto_

```protobuf
```proto
syntax = "proto3";
package example.proto;
message User {
Expand All @@ -145,7 +143,7 @@ val source = ParseProto.ProtoSource("user.proto", new java.io.File(".").getAbsol
val protobufProtocol: Protocol[Mu[ProtobufF]] = ParseProto.parseProto[IO, Mu[ProtobufF]].parse(source).unsafeRunSync()

val toMuProtocol: Protocol[Mu[ProtobufF]] => mu.Protocol[Mu[MuF]] = { p: Protocol[Mu[ProtobufF]] =>
mu.Protocol.fromProtobufProto(CompressionType.Identity, true)(p)
mu.Protocol.fromProtobufProto(CompressionType.Identity)(p)
}

val printProtocolAsScala: mu.Protocol[Mu[MuF]] => Either[String, String] = { p =>
Expand All @@ -162,13 +160,10 @@ println("=====")

It would generate the following output:


```scala mdoc:passthrough
println("```scala")
(toMuProtocol >>> println)(protobufProtocol)
println("=====")
(toMuProtocol >>> printProtocolAsScala >>> println)(protobufProtocol)
println("```")
```

#### Proto2 Incompatibility
Expand Down
16 changes: 4 additions & 12 deletions microsite/docs/docs/optimizations.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,33 +49,25 @@ they're inside a product themselves. And we do this with the
def nestedNamedTypesTrans[T](implicit T: Basis[MuF, T]): Trans[MuF, MuF, T] = Trans {
case TProduct(name, fields, np, nc) =>
def nameTypes(f: Field[T]): Field[T] = f.copy(tpe = namedTypes(T)(f.tpe))
TProduct[T](
name,
fields.map(nameTypes),
np,
nc
)
TProduct[T](name, fields.map(nameTypes), np, nc)
case other => other
}

def namedTypesTrans[T]: Trans[MuF, MuF, T] = Trans {
case TProduct(name, _, _, _) => TNamedType[T](Nil, name)
case TSum(name, _) => TNamedType[T](Nil, name)
case other => other
case TSum(name, _) => TNamedType[T](Nil, name)
case other => other
}

def namedTypes[T: Basis[MuF, ?]]: T => T = scheme.cata(namedTypesTrans.algebra)
def nestedNamedTypes[T: Basis[MuF, ?]]: T => T = scheme.cata(nestedNamedTypesTrans.algebra)

```

and then apply the `namedTypes` combinator to the AST:

```scala mdoc:invisible
```scala mdoc
def ast = Mu(TNull[Mu[MuF]]())
```

```scala mdoc
val optimization = Optimize.namedTypes[Mu[MuF]]

optimization(ast)
Expand Down
18 changes: 10 additions & 8 deletions microsite/docs/docs/schemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ Currently in skeuomorph there are schemas defined for different cases:

Currently, Skeuomorph only supports proto3 compliance, and the recommended approach when using skeuomorph with [mu][]
is to use proto3 for all gRPC communications. While it is still possible to generate valid Scala code from a proto2 spec,
Skeuomorph will _not_ generate case classes for optional fields. For example, given a schema that looks like this:
Skeuomorph will _not_ generate case classes for optional fields. For example, given a `hello.proto` schema that looks like this:

```protobuf mdoc:silent
```proto
syntax = "proto2";
package src.main.hello;
package src.main;
message SayHelloRequest {
optional string name = 1;
Expand All @@ -44,15 +44,17 @@ service HelloWorldService {
}
```

Skeuomorph (with mu) will generate the following Scala code:
Skeuomorph (with mu and default plugin options) will generate the following Scala code:

```scala
object hello {
final case class SayHelloRequest(name: String)
final case class SayHelloResponse(message: String)
@service(Protobuf, Identity, namespace = Some("src.main.hello"), methodNameStyle = Capitalize)

final case class SayHelloRequest(name: _root_.java.lang.String)
final case class SayHelloResponse(message: _root_.java.lang.String)

@service(Protobuf, compressionType = Identity, namespace = Some("src.main"))
trait HelloWorldService[F[_]] {
def SayHello(req: src.main.hello.hello.SayHelloRequest): F[src.main.hello.hello.SayHelloResponse]
def SayHello(req: _root_.src.main.hello.SayHelloRequest): F[_root_.src.main.hello.SayHelloResponse]
}
}
```
Expand Down
4 changes: 2 additions & 2 deletions microsite/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
layout: homeFeatures
features:
- first: ["Non-recursive ADTs", "Declare languages as constructors in a simple way"]
- second: ["Transformations & optimizations", "Apply nanopass optimizations to the Abstract Syntax Trees of your program"]
- third: ["Recursion Schemes", "Leverage the power of Recursion Schemes to make performant and easy to write programs on your ADTs"]
- second: ["Transformations & optimizations", "Apply nanopass optimizations to the Abstract Syntax Trees of your program", "schemas"]
- third: ["Recursion Schemes", "Leverage the power of Recursion Schemes to make performant and easy to write programs on your ASTs", "optimizations"]
---
10 changes: 4 additions & 6 deletions src/main/scala/higherkindness/skeuomorph/mu/codegen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,11 @@ object codegen {
val serializationType = Term.Name(srv.serializationType.toString)
val compressionType = Term.Name(srv.compressionType.toString)

val serviceAnnotation = srv.idiomaticEndpoints match {
case IdiomaticEndpoints(Some(pkg), true) =>
mod"@service($serializationType, $compressionType, namespace = Some($pkg), methodNameStyle = Capitalize)"
case IdiomaticEndpoints(None, true) =>
mod"@service($serializationType, $compressionType, methodNameStyle = Capitalize)"
val serviceAnnotation = srv.namespace match {
case Some(namespace) if srv.useIdiomaticEndpoints =>
mod"@service($serializationType, compressionType = $compressionType, namespace = Some($namespace))"
case _ =>
mod"@service($serializationType, $compressionType)"
mod"@service($serializationType, compressionType = $compressionType, namespace = None)"
}

srv.operations.traverse(op => operation(op, streamCtor)).map { ops =>
Expand Down
33 changes: 16 additions & 17 deletions src/main/scala/higherkindness/skeuomorph/mu/protocol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,15 @@

package higherkindness.skeuomorph.mu

import higherkindness.skeuomorph.protobuf
import higherkindness.skeuomorph.protobuf.ProtobufF
import higherkindness.skeuomorph.avro
import higherkindness.droste._
import higherkindness.skeuomorph.avro.AvroF
import higherkindness.skeuomorph.mu.Service.OperationType
import higherkindness.skeuomorph.mu.Transform.transformAvro
import higherkindness.skeuomorph.mu.Transform.transformProto
import higherkindness.droste._
import higherkindness.skeuomorph.mu.Transform._
import higherkindness.skeuomorph._
import higherkindness.skeuomorph.protobuf.ProtobufF

sealed trait SerializationType extends Product with Serializable
object SerializationType {
private[skeuomorph] sealed trait SerializationType extends Product with Serializable
private[skeuomorph] object SerializationType {
case object Protobuf extends SerializationType
case object Avro extends SerializationType
case object AvroWithSchema extends SerializationType
Expand All @@ -38,8 +36,6 @@ object CompressionType {
case object Identity extends CompressionType
}

final case class IdiomaticEndpoints(pkg: Option[String], value: Boolean)

final case class Protocol[T](
name: Option[String],
pkg: Option[String],
Expand All @@ -53,7 +49,7 @@ object Protocol {
/**
* create a [[higherkindness.skeuomorph.mu.Protocol]] from a [[higherkindness.skeuomorph.avro.Protocol]]
*/
def fromAvroProtocol[T, U](compressionType: CompressionType, useIdiomaticEndpoints: Boolean)(
def fromAvroProtocol[T, U](compressionType: CompressionType, useIdiomaticEndpoints: Boolean = true)(
proto: avro.Protocol[T]
)(implicit T: Basis[AvroF, T], U: Basis[MuF, U]): Protocol[U] = {

Expand All @@ -76,15 +72,16 @@ object Protocol {
proto.name,
SerializationType.Avro,
compressionType,
IdiomaticEndpoints(proto.namespace, useIdiomaticEndpoints),
proto.namespace,
useIdiomaticEndpoints,
proto.messages.map(toOperation)
)
),
imports = Nil
)
}

def fromProtobufProto[T, U](compressionType: CompressionType, useIdiomaticEndpoints: Boolean)(
def fromProtobufProto[T, U](compressionType: CompressionType, useIdiomaticEnpoints: Boolean = true)(
protocol: protobuf.Protocol[T]
)(implicit T: Basis[ProtobufF, T], U: Basis[MuF, U]): Protocol[U] = {
val toMu: T => U = scheme.cata(transformProto[U].algebra)
Expand All @@ -99,18 +96,19 @@ object Protocol {
val toImports: DependentImport[T] => DependentImport[U] =
imp => DependentImport(imp.pkg, imp.protocol, toMu(imp.tpe))

new Protocol[U](
Protocol[U](
name = Some(protocol.name),
pkg = Option(protocol.pkg),
options = protocol.options,
declarations = protocol.declarations.map(toMu),
services = protocol.services
.map(s =>
new Service[U](
Service(
s.name,
SerializationType.Protobuf,
compressionType,
IdiomaticEndpoints(Option(protocol.pkg), useIdiomaticEndpoints),
Option(protocol.pkg),
useIdiomaticEnpoints,
s.operations.map(toOperation)
)
),
Expand All @@ -125,7 +123,8 @@ final case class Service[T](
name: String,
serializationType: SerializationType,
compressionType: CompressionType,
idiomaticEndpoints: IdiomaticEndpoints,
namespace: Option[String],
useIdiomaticEndpoints: Boolean,
operations: List[Service.Operation[T]]
)
object Service {
Expand Down
4 changes: 2 additions & 2 deletions src/test/resources/avro/GreeterService.avdl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@namespace("foo.bar")
@namespace("com.acme")
protocol MyGreeterService {

record HelloRequest {
Expand All @@ -13,7 +13,7 @@ protocol MyGreeterService {
array<string> arg3;
}

foo.bar.HelloResponse sayHelloAvro(foo.bar.HelloRequest arg);
com.acme.HelloResponse sayHelloAvro(com.acme.HelloRequest arg);

void sayNothingAvro();
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2018-2020 47 Degrees Open Source <https://www.47deg.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package higherkindness.skeuomorph.avro

import higherkindness.skeuomorph.instances._
import org.typelevel.discipline.specs2.Discipline
import cats.laws.discipline.{FoldableTests, FunctorTests, TraverseTests}
import cats.implicits._
import org.specs2._

class AvroCatsLawsSpec extends Specification with ScalaCheck with Discipline {

def is = s2"""
$traverse
$functor
$foldable
"""

val traverse = checkAll("Traverse[AvroF]", TraverseTests[AvroF].traverse[Int, Int, Int, Set[Int], Option, Option])
val functor = checkAll("Functor[AvroF]", FunctorTests[AvroF].functor[Int, Int, String])
val foldable = checkAll("Foldable[AvroF]", FoldableTests[AvroF].foldable[Int, Int])
}

0 comments on commit 7e4498b

Please sign in to comment.