Skip to content

Scala 3: edit sources on-the-fly in sbt to support @pre213 methods in shared source code #4113

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 5, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,23 +72,27 @@ sealed trait HttpMessage extends jm.HttpMessage {
def discardEntityBytes(system: ClassicActorSystemProvider): HttpMessage.DiscardedEntity = entity.discardBytes()(SystemMaterializer(system).materializer)

/** Returns a copy of this message with the list of headers set to the given ones. */
/*@pre213
def withHeaders(headers: HttpHeader*): Self = withHeaders(headers.toList)*/

/** Returns a copy of this message with the list of headers set to the given ones. */
def withHeaders(headers: immutable.Seq[HttpHeader]): Self
@pre213
def withHeaders(headers: HttpHeader*): Self = withHeaders(headers.toList)

/** Returns a copy of this message with the list of headers set to the given ones. */
@since213
def withHeaders(firstHeader: HttpHeader, otherHeaders: HttpHeader*): Self =
withHeaders(firstHeader +: otherHeaders.toList)

/** Returns a copy of this message with the list of headers set to the given ones. */
def withHeaders(headers: immutable.Seq[HttpHeader]): Self

/**
* Returns a new message that contains all of the given default headers which didn't already
* exist (by case-insensitive header name) in this message.
*/
/*@pre213
def withDefaultHeaders(defaultHeaders: HttpHeader*): Self = withDefaultHeaders(defaultHeaders.toList)*/
@pre213
def withDefaultHeaders(defaultHeaders: HttpHeader*): Self = withDefaultHeaders(defaultHeaders.toList)

@since213
def withDefaultHeaders(firstHeader: HttpHeader, otherHeaders: HttpHeader*): Self =
withDefaultHeaders(firstHeader +: otherHeaders.toList)

/**
* Returns a new message that contains all of the given default headers which didn't already
Expand All @@ -100,10 +104,6 @@ sealed trait HttpMessage extends jm.HttpMessage {
else defaultHeaders.foldLeft(headers) { (acc, h) => if (headers.exists(_ is h.lowercaseName)) acc else h +: acc }
}

@since213
def withDefaultHeaders(firstHeader: HttpHeader, otherHeaders: HttpHeader*): Self =
withDefaultHeaders(firstHeader +: otherHeaders.toList)

/** Returns a copy of this message with the attributes set to the given ones. */
def withAttributes(headers: Map[AttributeKey[_], _]): Self

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ object CacheDirectives {
* http://tools.ietf.org/html/rfc7234#section-5.2.1.4
*/
case object `no-cache` extends SingletonValueRenderable with RequestDirective with ResponseDirective {
/*@pre213
@pre213
def apply(fieldNames: String*): `no-cache` =
new `no-cache`(immutable.Seq(fieldNames: _*))*/
new `no-cache`(immutable.Seq(fieldNames: _*))
@since213
def apply(firstFieldName: String, otherFieldNames: String*): `no-cache` =
new `no-cache`(firstFieldName +: otherFieldNames.toList)
Expand Down Expand Up @@ -138,8 +138,8 @@ object CacheDirectives {
*/
final case class `private`(fieldNames: immutable.Seq[String]) extends FieldNamesDirective with ResponseDirective
object `private` {
/*@pre213
def apply(fieldNames: String*): `private` = new `private`(immutable.Seq(fieldNames: _*))*/
@pre213
def apply(fieldNames: String*): `private` = new `private`(immutable.Seq(fieldNames: _*))
@since213
def apply(): `private` = new `private`(immutable.Seq.empty)
@since213
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ object Language {
val tags = compoundTag.split('-')
new Language(tags.head, immutable.Seq(tags.tail: _*))
} else new Language(compoundTag, immutable.Seq.empty)
/*@pre213
@pre213
def apply(primaryTag: String, subTags: String*): Language =
new Language(primaryTag, immutable.Seq(subTags: _*))*/
new Language(primaryTag, immutable.Seq(subTags: _*))
@since213
def apply(primaryTag: String, firstSubTag: String, otherSubTags: String*): Language =
new Language(primaryTag, firstSubTag +: otherSubTags)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ final case class LinkValue(uri: Uri, params: immutable.Seq[LinkParam]) extends j
}

object LinkValue {
/*@pre213
def apply(uri: Uri, params: LinkParam*): LinkValue = apply(uri, immutable.Seq(params: _*))*/
@pre213
def apply(uri: Uri, params: LinkParam*): LinkValue = apply(uri, immutable.Seq(params: _*))
@since213
def apply(uri: Uri, firstParam: LinkParam, otherParams: LinkParam*): LinkValue = apply(uri, firstParam +: otherParams)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,9 @@ import akka.http.impl.util.JavaMapping.Implicits._

// https://tools.ietf.org/html/rfc7231#section-5.3.2
object Accept extends ModeledCompanion[Accept] {
/*@pre213
@pre213
def apply(mediaRanges: MediaRange*): Accept =
apply(immutable.Seq(mediaRanges: _*))*/
apply(immutable.Seq(mediaRanges: _*))
@since213
def apply(firstMediaRange: MediaRange, otherMediaRanges: MediaRange*): Accept =
apply(firstMediaRange +: otherMediaRanges)
Expand Down Expand Up @@ -172,9 +172,9 @@ final case class `Accept-Charset`(charsetRanges: immutable.Seq[HttpCharsetRange]

// https://tools.ietf.org/html/rfc7231#section-5.3.4
object `Accept-Encoding` extends ModeledCompanion[`Accept-Encoding`] {
/*@pre213
@pre213
def apply(encodings: HttpEncodingRange*): `Accept-Encoding` =
apply(immutable.Seq(encodings: _*))*/
apply(immutable.Seq(encodings: _*))
@since213
def apply(): `Accept-Encoding` =
apply(immutable.Seq.empty)
Expand Down Expand Up @@ -211,9 +211,9 @@ final case class `Accept-Language`(languages: immutable.Seq[LanguageRange]) exte

// https://tools.ietf.org/html/rfc7233#section-2.3
object `Accept-Ranges` extends ModeledCompanion[`Accept-Ranges`] {
/*@pre213
@pre213
def apply(rangeUnits: RangeUnit*): `Accept-Ranges` =
apply(immutable.Seq(rangeUnits: _*))*/
apply(immutable.Seq(rangeUnits: _*))
@since213
def apply(): `Accept-Ranges` =
apply(immutable.Seq.empty)
Expand Down Expand Up @@ -242,9 +242,9 @@ final case class `Access-Control-Allow-Credentials`(allow: Boolean)

// https://www.w3.org/TR/cors/#access-control-allow-headers-response-header
object `Access-Control-Allow-Headers` extends ModeledCompanion[`Access-Control-Allow-Headers`] {
/*@pre213
@pre213
def apply(headers: String*): `Access-Control-Allow-Headers` =
apply(immutable.Seq(headers: _*))*/
apply(immutable.Seq(headers: _*))
@since213
def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Allow-Headers` =
apply(firstHeader +: otherHeaders)
Expand All @@ -262,9 +262,9 @@ final case class `Access-Control-Allow-Headers`(headers: immutable.Seq[String])

// https://www.w3.org/TR/cors/#access-control-allow-methods-response-header
object `Access-Control-Allow-Methods` extends ModeledCompanion[`Access-Control-Allow-Methods`] {
/*@pre213
@pre213
def apply(methods: HttpMethod*): `Access-Control-Allow-Methods` =
apply(immutable.Seq(methods: _*))*/
apply(immutable.Seq(methods: _*))
@since213
def apply(firstMethod: HttpMethod, otherMethods: HttpMethod*): `Access-Control-Allow-Methods` =
apply(firstMethod +: otherMethods)
Expand Down Expand Up @@ -303,9 +303,9 @@ final case class `Access-Control-Allow-Origin` private (range: HttpOriginRange)

// https://www.w3.org/TR/cors/#access-control-expose-headers-response-header
object `Access-Control-Expose-Headers` extends ModeledCompanion[`Access-Control-Expose-Headers`] {
/*@pre213
@pre213
def apply(headers: String*): `Access-Control-Expose-Headers` =
apply(immutable.Seq(headers: _*))*/
apply(immutable.Seq(headers: _*))
@since213
def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Expose-Headers` =
apply(firstHeader +: otherHeaders)
Expand All @@ -331,9 +331,9 @@ final case class `Access-Control-Max-Age`(deltaSeconds: Long) extends jm.headers

// https://www.w3.org/TR/cors/#access-control-request-headers-request-header
object `Access-Control-Request-Headers` extends ModeledCompanion[`Access-Control-Request-Headers`] {
/*@pre213
@pre213
def apply(headers: String*): `Access-Control-Request-Headers` =
apply(immutable.Seq(headers: _*))*/
apply(immutable.Seq(headers: _*))
@since213
def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Request-Headers` =
apply(firstHeader +: otherHeaders)
Expand Down Expand Up @@ -366,9 +366,9 @@ final case class Age(deltaSeconds: Long) extends jm.headers.Age with ResponseHea

// https://tools.ietf.org/html/rfc7231#section-7.4.1
object Allow extends ModeledCompanion[Allow] {
/*@pre213
@pre213
def apply(methods: HttpMethod*): Allow =
apply(immutable.Seq(methods: _*))*/
apply(immutable.Seq(methods: _*))
@since213
def apply(): `Allow` =
apply(immutable.Seq.empty)
Expand Down Expand Up @@ -546,8 +546,8 @@ final case class `Content-Type` private[http] (contentType: ContentType) extends
object Cookie extends ModeledCompanion[Cookie] {
def apply(first: HttpCookiePair, more: HttpCookiePair*): Cookie = apply(immutable.Seq(first +: more: _*))
def apply(name: String, value: String): Cookie = apply(HttpCookiePair(name, value))
/*@pre213
def apply(values: (String, String)*): Cookie = apply(values.map(HttpCookiePair(_)).toList)*/
@pre213
def apply(values: (String, String)*): Cookie = apply(values.map(HttpCookiePair(_)).toList)
@since213
def apply(first: (String, String), more: (String, String)*): Cookie = apply((first +: more).map(HttpCookiePair(_)))
implicit val cookiePairsRenderer: Renderer[immutable.Iterable[HttpCookiePair]] = Renderer.seqRenderer[HttpCookiePair](separator = "; ") // cache
Expand Down Expand Up @@ -695,8 +695,8 @@ final case class `Last-Modified`(date: DateTime) extends jm.headers.LastModified
// https://tools.ietf.org/html/rfc5988#section-5
object Link extends ModeledCompanion[Link] {
def apply(uri: Uri, first: LinkParam, more: LinkParam*): Link = apply(immutable.Seq(LinkValue(uri, first +: more.toList)))
/*@pre213
def apply(values: LinkValue*): Link = apply(immutable.Seq(values: _*))*/
@pre213
def apply(values: LinkValue*): Link = apply(immutable.Seq(values: _*))
@since213
def apply(firstValue: LinkValue, otherValues: LinkValue*): Link = apply(firstValue +: otherValues)

Expand All @@ -723,8 +723,8 @@ final case class Location(uri: Uri) extends jm.headers.Location with ResponseHea

// https://tools.ietf.org/html/rfc6454#section-7
object Origin extends ModeledCompanion[Origin] {
/*@pre213
def apply(origins: HttpOrigin*): Origin = apply(immutable.Seq(origins: _*))*/
@pre213
def apply(origins: HttpOrigin*): Origin = apply(immutable.Seq(origins: _*))
@since213
def apply(firstOrigin: HttpOrigin, otherOrigins: HttpOrigin*): Origin = apply(firstOrigin +: otherOrigins)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ trait FormFieldDirectives extends FormFieldDirectivesInstances with ToNameRecept
*
* @group form
*/
/*@pre213
@pre213
@deprecated("Use new `formField` overloads with FieldSpec parameters. Kept for binary compatibility", "10.2.0")
private[http] def formField(pdm: FieldMagnet): pdm.Out = formFields(pdm)*/
private[http] def formField(pdm: FieldMagnet): pdm.Out = formFields(pdm)

/**
* Extracts an HTTP form field from the request.
Expand All @@ -74,10 +74,10 @@ trait FormFieldDirectives extends FormFieldDirectivesInstances with ToNameRecept
*
* @group form
*/
/*@pre213
@pre213
@deprecated("Use new `formField` overloads with FieldSpec parameters. Kept for binary compatibility", "10.2.0")
private[http] def formFields(pdm: FieldMagnet): pdm.Out =
pdm.convert(toStrictEntity(StrictForm.toStrictTimeout).wrap { pdm() })*/
pdm.convert(toStrictEntity(StrictForm.toStrictTimeout).wrap { pdm() })

/**
* Extracts a number of HTTP form field from the request.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ trait RespondWithDirectives {
*
* @group response
*/
/*@pre213
@pre213
def respondWithHeaders(responseHeaders: HttpHeader*): Directive0 =
respondWithHeaders(responseHeaders.toList)*/
respondWithHeaders(responseHeaders.toList)

/**
* Unconditionally adds the given response headers to all HTTP responses of its inner Route.
Expand All @@ -59,9 +59,9 @@ trait RespondWithDirectives {
*
* @group response
*/
/*@pre213
@pre213
def respondWithDefaultHeaders(responseHeaders: HttpHeader*): Directive0 =
respondWithDefaultHeaders(responseHeaders.toList)*/
respondWithDefaultHeaders(responseHeaders.toList)

/**
* Adds the given response headers to all HTTP responses of its inner Route,
Expand Down
5 changes: 5 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ lazy val httpCore = project("akka-http-core")
.settings(scalaMacroSupport)
.enablePlugins(BootstrapGenjavadoc)
.enablePlugins(ReproducibleBuildsPlugin)
.enablePlugins(Pre213Preprocessor).settings(
akka.http.sbt.Pre213Preprocessor.pre213Files := Seq(
"headers.scala", "HttpMessage.scala", "LanguageRange.scala", "CacheDirective.scala", "LinkValue.scala"
)
)
.disablePlugins(ScalafixPlugin)

lazy val http = project("akka-http")
Expand Down
36 changes: 36 additions & 0 deletions project/Pre213Preprocessor.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package akka.http.sbt

import sbt._
import Keys._

object Pre213Preprocessor extends AutoPlugin {
val pre213Files = settingKey[Seq[String]]("files that should be edited for pre213 annotation")

val pattern = """(?s)@pre213.*?@since213""".r
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we've come a far way from (only) running regex on URLs...


override def projectSettings: Seq[Def.Setting[_]] = {
Compile / sources := {
if (scalaVersion.value startsWith "3") {
val filter = pre213Files.value.toSet
(Compile / sources).value.map { s =>
if (filter(s.getName)) {
val data = IO.read(s)
val targetFile = sourceManaged.value / s.getName
val newData = pattern.replaceAllIn(data, "@since213")
IO.write(targetFile, newData)
targetFile
} else s
}
} else (Compile / sources).value
}
}
}

object ReplaceApp extends App {
val pattern = """(?s)@pre213.*?@since213""".r
val f = file("/home/johannes/git/opensource/akka-http/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala")
val data = IO.read(f)
val targetFile = file("/tmp/test")
val newData = pattern.replaceAllIn(data, "@since213")
IO.write(targetFile, newData)
}