Skip to content

Commit

Permalink
Disable braceless syntax on Scala 3
Browse files Browse the repository at this point in the history
  • Loading branch information
MateuszKubuszok committed Aug 15, 2024
1 parent d8db055 commit 283120e
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 80 deletions.
18 changes: 15 additions & 3 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,21 @@ project.includePaths."+" = ["glob:**/docs/**.md"]
maxColumn = 120
runner.dialect = Scala213Source3
fileOverride {
"glob:**/src/main/scala-3/**" { runner.dialect = scala3 }
"glob:**/src/test/scala-3/**" { runner.dialect = scala3 }
"glob:**/scripts/**" { runner.dialect = scala3 }
"glob:**/src/main/scala-3/**" {
runner.dialect = scala3
runner.dialectOverride.allowSignificantIndentation = false
runner.dialectOverride.allowQuietSyntax = true
}
"glob:**/src/test/scala-3/**" {
runner.dialect = scala3
runner.dialectOverride.allowSignificantIndentation = false
runner.dialectOverride.allowQuietSyntax = true
}
"glob:**/scripts/**" {
runner.dialect = scala3
runner.dialectOverride.allowSignificantIndentation = false
runner.dialectOverride.allowQuietSyntax = true
}
// for we we have to:
// - replace ```scala with ```scala mdoc (MkDocs does NOT support these suffixes)
// - run scalafmt --check docs/docs
Expand Down
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ val settings = Seq(
"-explain",
"-explain-types",
"-feature",
"-no-indent",
"-Wconf:msg=Unreachable case:s", // suppress fake (?) errors in internal.compiletime
"-Wnonunit-statement",
// "-Wunused:imports", // import x.Underlying as X is marked as unused even though it is! probably one of https://github.com/scala/scala3/issues/: #18564, #19252, #19657, #19912
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,20 @@ private[compiletime] trait ExprPromisesPlatform extends ExprPromises { this: Def
Symbol.spliceOwner,
platformSpecific.freshTerm(prefix),
TypeRepr.of[A],
usageHint match
usageHint match {
case UsageHint.None => Flags.EmptyFlags
case UsageHint.Lazy => Flags.Lazy
case UsageHint.Var => Flags.Mutable
,
},
Symbol.noSymbol
)
private def freshTermName[A: Type](usageHint: UsageHint): ExprPromiseName = {
// To keep things consistent with Scala 2 for e.g. "Some[String]" we should generate "some" rather than
// "some[string], so we need to remove types applied to type constructor.
val repr = TypeRepr.of[A] match
val repr = TypeRepr.of[A] match {
case AppliedType(repr, _) => repr
case otherwise => otherwise
}
freshTermName(repr.show(using Printer.TypeReprShortCode).toLowerCase, usageHint)
}
private def freshTermName[A: Type](expr: Expr[?], usageHint: UsageHint): ExprPromiseName =
Expand Down Expand Up @@ -136,13 +137,13 @@ private[compiletime] trait ExprPromisesPlatform extends ExprPromises { this: Def

val sym = TypeRepr.of[SomeFrom].typeSymbol
if sym.flags.is(Flags.Enum) && (sym.flags.is(Flags.JavaStatic) || sym.flags.is(Flags.StableRealizable)) then
// Scala 3's enums' parameterless cases are vals with type erased, so w have to match them by value
// case arg @ Enum.Value => ...
CaseDef(Bind(bindName, Ident(sym.termRef)), None, body)
// Scala 3's enums' parameterless cases are vals with type erased, so w have to match them by value
// case arg @ Enum.Value => ...
CaseDef(Bind(bindName, Ident(sym.termRef)), None, body)
else if sym.flags.is(Flags.Module) then
// case objects are also matched by value but the tree for them is generated in a slightly different way
// case arg @ Enum.Value => ...
CaseDef(Bind(bindName, Ident(sym.companionModule.termRef)), None, body)
// case objects are also matched by value but the tree for them is generated in a slightly different way
// case arg @ Enum.Value => ...
CaseDef(Bind(bindName, Ident(sym.companionModule.termRef)), None, body)
else
// case arg : Enum.Value => ...
CaseDef(Bind(bindName, Typed(Wildcard(), TypeTree.of[SomeFrom])), None, body)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ private[compiletime] trait TypesPlatform extends Types { this: DefinitionsPlatfo
}

/** What is the type of each method parameter */
def paramsWithTypes(tpe: TypeRepr, method: Symbol, isConstructor: Boolean): Map[String, TypeRepr] =
def paramsWithTypes(tpe: TypeRepr, method: Symbol, isConstructor: Boolean): Map[String, TypeRepr] = {
// constructor methods still have to have their type parameters manually applied,
// even if we know the exact type of their class
val appliedIfNecessary =
Expand Down Expand Up @@ -68,6 +68,7 @@ private[compiletime] trait TypesPlatform extends Types { this: DefinitionsPlatfo
)
// $COVERAGE-ON$
}
}

/** Applies type arguments from supertype to subtype if there are any */
def subtypeTypeOf[A: Type](subtype: Symbol): ?<[A] =
Expand All @@ -94,10 +95,9 @@ private[compiletime] trait TypesPlatform extends Types { this: DefinitionsPlatfo
final def apply[A <: U](value: A): Type[A] =
ConstantType(lift(value)).asType.asInstanceOf[Type[A]]
final def unapply[A](A: Type[A]): Option[Existential.UpperBounded[U, Id]] =
if A <:< Type[U] then
quoted.Type
.valueOfConstant[U](using A.asInstanceOf[Type[U]])
.map(Existential.UpperBounded[U, Id, U](_))
if A <:< Type[U] then quoted.Type
.valueOfConstant[U](using A.asInstanceOf[Type[U]])
.map(Existential.UpperBounded[U, Id, U](_))
else None
}
}
Expand Down Expand Up @@ -246,9 +246,10 @@ private[compiletime] trait TypesPlatform extends Types { this: DefinitionsPlatfo
// while in Scala 2 macros it dealiases everything - to keep the same behavior between them we need to
// apply recursive dealiasing ourselves.
def dealiasAll(tpe: TypeRepr): TypeRepr =
tpe match
tpe match {
case AppliedType(tycon, args) => AppliedType(dealiasAll(tycon), args.map(dealiasAll(_)))
case _ => tpe.dealias
}

val repr = dealiasAll(TypeRepr.of[A])

Expand All @@ -260,10 +261,10 @@ private[compiletime] trait TypesPlatform extends Types { this: DefinitionsPlatfo

// Classes defined inside a "class" or "def" have package.name.ClassName removed from the type,
// so we have to prepend it ourselves to keep behavior consistent with Scala 2.
if symbolFullName != colorlessReprName && symbolFullName.endsWith("__" + colorlessReprName) then
symbolFullName.substring(0, symbolFullName.length - 2 - colorlessReprName.length) + colorfulReprName
else if symbolFullName != colorlessReprName && symbolFullName.endsWith("_" + colorlessReprName) then
symbolFullName.substring(0, symbolFullName.length - 1 - colorlessReprName.length) + colorfulReprName
if symbolFullName != colorlessReprName && symbolFullName.endsWith("__" + colorlessReprName)
then symbolFullName.substring(0, symbolFullName.length - 2 - colorlessReprName.length) + colorfulReprName
else if symbolFullName != colorlessReprName && symbolFullName.endsWith("_" + colorlessReprName)
then symbolFullName.substring(0, symbolFullName.length - 1 - colorlessReprName.length) + colorfulReprName
else colorfulReprName
}
.getOrElse(repr.toString)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ trait ProductTypesPlatform extends ProductTypes { this: DefinitionsPlatform =>
object platformSpecific {

// to align API between Scala versions
extension (sym: Symbol)
extension (sym: Symbol) {
def isAbstract: Boolean = !sym.isNoSymbol && sym.flags.is(Flags.Abstract) || sym.flags.is(Flags.Trait)

def isPublic: Boolean = !sym.isNoSymbol &&
!(sym.flags.is(Flags.Private) || sym.flags.is(Flags.PrivateLocal) || sym.flags.is(Flags.Protected) ||
sym.privateWithin.isDefined || sym.protectedWithin.isDefined)
}

def isParameterless(method: Symbol): Boolean =
method.paramSymss.filterNot(_.exists(_.isType)).flatten.isEmpty
Expand Down Expand Up @@ -122,8 +123,8 @@ trait ProductTypesPlatform extends ProductTypes { this: DefinitionsPlatform =>
isInherited = !localDefinitions(getter),
get =
// TODO: pathological cases like def foo[Unused]()()()
if getter.paramSymss.isEmpty then
(in: Expr[A]) => in.asTerm.select(getter).appliedToArgss(Nil).asExprOf[tpe.Underlying]
if getter.paramSymss.isEmpty then (in: Expr[A]) =>
in.asTerm.select(getter).appliedToArgss(Nil).asExprOf[tpe.Underlying]
else (in: Expr[A]) => in.asTerm.select(getter).appliedToNone.asExprOf[tpe.Underlying]
)
}
Expand Down
Loading

0 comments on commit 283120e

Please sign in to comment.