Skip to content

Use extension methods #9407

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 1 commit into from
Jul 25, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/CompilationUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import tpd.{Tree, TreeTraverser}
import typer.PrepareInlineable.InlineAccessors
import typer.Nullables
import transform.SymUtils._
import core.Decorators.{given _}
import core.Decorators._
import config.SourceVersion

class CompilationUnit protected (val source: SourceFile) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package ast
import core._
import util.Spans._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._
import Symbols._, StdNames._, Trees._, Phases._, ContextOps._
import Decorators.{given _}, transform.SymUtils._
import Decorators._, transform.SymUtils._
import NameKinds.{UniqueName, EvidenceParamName, DefaultGetterName}
import typer.{FrontEnd, Namer}
import util.{Property, SourceFile, SourcePosition}
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
/** Structural tree comparison (since == on trees is reference equality).
* For the moment, only Ident, Select, Literal, Apply and TypeApply are supported
*/
implicit class StructuralEqDeco(t1: Tree) {
extension (t1: Tree) {
def === (t2: Tree)(using Context): Boolean = (t1, t2) match {
case (t1: Ident, t2: Ident) =>
t1.symbol == t2.symbol
Expand Down
5 changes: 2 additions & 3 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import transform.TypeUtils._
import core._
import util.Spans._, Types._, Contexts._, Constants._, Names._, Flags._, NameOps._
import Symbols._, StdNames._, Annotations._, Trees._, Symbols._
import Decorators.{given _}, DenotTransformers._
import Decorators._, DenotTransformers._
import collection.{immutable, mutable}
import util.{Property, SourceFile, NoSource}
import NameKinds.{TempResultName, OuterSelectName}
Expand Down Expand Up @@ -1111,12 +1111,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
!(sym.is(Method) && sym.info.isInstanceOf[MethodOrPoly]) // if is a method it is parameterless
}

implicit class ListOfTreeDecorator(val xs: List[tpd.Tree]) extends AnyVal {
extension (xs: List[tpd.Tree]):
def tpes: List[Type] = xs match {
case x :: xs1 => x.tpe :: xs1.tpes
case nil => Nil
}
}

/** A trait for loaders that compute trees. Currently implemented just by DottyUnpickler. */
trait TreeProvider {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
package dotty.tools.dotc.classpath

import dotty.tools.io.{AbstractFile, VirtualDirectory}
import FileUtils.AbstractFileOps
import FileUtils._
import dotty.tools.io.ClassPath
import dotty.tools.dotc.core.Contexts._

Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/classpath/FileUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import dotty.tools.io.AbstractFile
* Common methods related to Java files and abstract files used in the context of classpath
*/
object FileUtils {
implicit class AbstractFileOps(val file: AbstractFile) extends AnyVal {
extension (file: AbstractFile) {
def isPackage: Boolean = file.isDirectory && mayBeValidPackage(file.name)

def isClass: Boolean = !file.isDirectory && file.hasExtension("class") && !file.name.endsWith("$class.class")
Expand All @@ -30,7 +30,7 @@ object FileUtils {
def toURLs(default: => Seq[URL] = Seq.empty): Seq[URL] = if (file.file == null) default else Seq(file.toURL)
}

implicit class FileOps(val file: JFile) extends AnyVal {
extension (file: JFile) {
def isPackage: Boolean = file.isDirectory && mayBeValidPackage(file.getName)

def isClass: Boolean = file.isFile && file.getName.endsWith(".class") && !file.getName.endsWith("$class.class")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import java.io.File
import java.net.URL

import dotty.tools.io.{ AbstractFile, FileZipArchive }
import FileUtils.AbstractFileOps
import FileUtils._
import dotty.tools.io.{ClassPath, ClassRepresentation}

/**
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/config/Settings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ object Settings {
}

object Setting {
implicit class SettingDecorator[T](val setting: Setting[T]) extends AnyVal {
extension [T](setting: Setting[T]) {
def value(using Context): T = setting.valueIn(ctx.settingsState)
def update(x: T)(using Context): SettingsState = setting.updateIn(ctx.settingsState, x)
def isDefault(using Context): Boolean = setting.isDefaultIn(ctx.settingsState)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -678,15 +678,15 @@ object Contexts {
end ops

// TODO: Fix issue when converting ModeChanges and FreshModeChanges to extension givens
implicit class ModeChanges(val c: Context) extends AnyVal {
extension (c: Context) {
final def withModeBits(mode: Mode): Context =
if (mode != c.mode) c.fresh.setMode(mode) else c

final def addMode(mode: Mode): Context = withModeBits(c.mode | mode)
final def retractMode(mode: Mode): Context = withModeBits(c.mode &~ mode)
}

implicit class FreshModeChanges(val c: FreshContext) extends AnyVal {
extension (c: FreshContext) {
final def addMode(mode: Mode): c.type = c.setMode(c.mode | mode)
final def retractMode(mode: Mode): c.type = c.setMode(c.mode &~ mode)
}
Expand Down
42 changes: 19 additions & 23 deletions compiler/src/dotty/tools/dotc/core/Decorators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,26 @@ object Decorators {
case s: String => termName(s)
case n: Name => n.toTermName

implicit class StringDecorator(val s: String) extends AnyVal {
extension (s: String):
def splitWhere(f: Char => Boolean, doDropIndex: Boolean): Option[(String, String)] = {
def splitAt(idx: Int, doDropIndex: Boolean): Option[(String, String)] =
if (idx == -1) None
else Some((s.take(idx), s.drop(if (doDropIndex) idx + 1 else idx)))

splitAt(s.indexWhere(f), doDropIndex)
}
}

/** Implements a findSymbol method on iterators of Symbols that
* works like find but avoids Option, replacing None with NoSymbol.
*/
implicit class SymbolIteratorDecorator(val it: Iterator[Symbol]) extends AnyVal {
extension (it: Iterator[Symbol]):
final def findSymbol(p: Symbol => Boolean): Symbol = {
while (it.hasNext) {
val sym = it.next()
if (p(sym)) return sym
}
NoSymbol
}
}

final val MaxFilterRecursions = 1000

Expand Down Expand Up @@ -161,29 +159,27 @@ object Decorators {
def & (ys: List[T]): List[T] = xs filter (ys contains _)
}

given ListOfListDecorator as AnyRef:
extension [T, U](xss: List[List[T]]):
def nestedMap(f: T => U): List[List[U]] =
xss.map(_.map(f))
def nestedMapConserve(f: T => U): List[List[U]] =
xss.mapconserve(_.mapconserve(f))
def nestedZipWithConserve(yss: List[List[U]])(f: (T, U) => T): List[List[T]] =
xss.zipWithConserve(yss)((xs, ys) => xs.zipWithConserve(ys)(f))
end extension

implicit class TextToString(val text: Text) extends AnyVal {
extension [T, U](xss: List[List[T]]):
def nestedMap(f: T => U): List[List[U]] =
xss.map(_.map(f))
def nestedMapConserve(f: T => U): List[List[U]] =
xss.mapconserve(_.mapconserve(f))
def nestedZipWithConserve(yss: List[List[U]])(f: (T, U) => T): List[List[T]] =
xss.zipWithConserve(yss)((xs, ys) => xs.zipWithConserve(ys)(f))
end extension

extension (text: Text):
def show(using Context): String = text.mkString(ctx.settings.pageWidth.value, ctx.settings.printLines.value)
}

/** Test whether a list of strings representing phases contains
* a given phase. See [[config.CompilerCommand#explainAdvanced]] for the
* exact meaning of "contains" here.
*/
implicit class PhaseListDecorator(val names: List[String]) extends AnyVal {
extension (names: List[String]) {
def containsPhase(phase: Phase): Boolean =
names.nonEmpty && {
phase match {
case phase: MegaPhase => phase.miniPhases.exists(containsPhase)
case phase: MegaPhase => phase.miniPhases.exists(x => names.containsPhase(x))
case _ =>
names exists { name =>
name == "all" || {
Expand All @@ -197,7 +193,7 @@ object Decorators {
}
}

implicit class reportDeco[T](x: T) extends AnyVal {
extension [T](x: T) {
def reporting(
op: WrappedResult[T] ?=> String,
printer: config.Printers.Printer = config.Printers.default): T = {
Expand All @@ -206,7 +202,7 @@ object Decorators {
}
}

implicit class genericDeco[T](val x: T) extends AnyVal {
extension [T](x: T) {
def assertingErrorsReported(using Context): T = {
assert(ctx.reporter.errorsReported)
x
Expand All @@ -217,7 +213,7 @@ object Decorators {
}
}

implicit class StringInterpolators(val sc: StringContext) extends AnyVal {
extension (sc: StringContext) {
/** General purpose string formatting */
def i(args: Any*)(using Context): String =
new StringFormatter(sc).assemble(args)
Expand All @@ -235,8 +231,8 @@ object Decorators {
explained(em(args: _*))
}

implicit class ArrayInterpolator[T <: AnyRef](val arr: Array[T]) extends AnyVal {
extension [T <: AnyRef](arr: Array[T]):
def binarySearch(x: T): Int = java.util.Arrays.binarySearch(arr.asInstanceOf[Array[Object]], x)
}

}

7 changes: 3 additions & 4 deletions compiler/src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Names._, StdNames._, Contexts._, Symbols._, Flags._, NameKinds._, Types._
import scala.internal.Chars
import Chars.isOperatorPart
import Definitions._
import nme._

object NameOps {

Expand Down Expand Up @@ -49,8 +50,7 @@ object NameOps {
}
}

implicit class NameDecorator[N <: Name](private val name: N) extends AnyVal {
import nme._
extension [N <: Name](name: N) {

def testSimple(f: SimpleName => Boolean): Boolean = name match {
case name: SimpleName => f(name)
Expand Down Expand Up @@ -268,8 +268,7 @@ object NameOps {
}
}

implicit class TermNameDecorator(private val name: TermName) extends AnyVal {
import nme._
extension (name: TermName) {

def setterName: TermName = name.exclude(FieldName) ++ str.SETTER_SUFFIX

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/NullOpsDecorator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import dotty.tools.dotc.core.Types._
/** Defines operations on nullable types. */
object NullOpsDecorator {

implicit class NullOps(val self: Type) {
extension (self: Type) {
/** Is this type exactly `UncheckedNull` (no vars, aliases, refinements etc allowed)? */
def isUncheckedNullType(using Context): Boolean = {
assert(ctx.explicitNulls)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Constants.Constant
import TypeApplications.TypeParamInfo
import Scopes.Scope
import dotty.tools.io.AbstractFile
import Decorators.SymbolIteratorDecorator
import Decorators._
import ast._
import ast.Trees.{LambdaTypeTree, TypeBoundsTree, ValDef, TypeDef}
import Trees.Literal
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import config.Config
import Contexts._, Symbols._, Flags._, SymDenotations._, Types._, Scopes._, Names._
import NameOps._
import StdNames.str
import Decorators.StringInterpolators
import Decorators._
import classfile.ClassfileParser
import util.Stats
import Decorators._
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ object Symbols {

NoDenotation // force it in order to set `denot` field of NoSymbol

implicit class Copier[N <: Name](sym: Symbol { type ThisName = N })(using Context) {
extension [N <: Name](sym: Symbol { type ThisName = N })(using Context) {
/** Copy a symbol, overriding selective fields.
* Note that `coord` and `associatedFile` will be set from the fields in `owner`, not
* the fields in `sym`.
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import scala.util.control.NonFatal
import typer.ProtoTypes.constrained
import typer.Applications.productSelectorTypes
import reporting.trace
import NullOpsDecorator.NullOps
import NullOpsDecorator._

/** Provides methods to compare types.
*/
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5650,7 +5650,7 @@ object Types {

implicit def decorateTypeApplications(tpe: Type): TypeApplications = new TypeApplications(tpe)

implicit class typeListDeco(val tps1: List[Type]) extends AnyVal {
extension (tps1: List[Type]) {
@tailrec def hashIsStable: Boolean =
tps1.isEmpty || tps1.head.hashIsStable && tps1.tail.hashIsStable
@tailrec def equalElements(tps2: List[Type], bs: BinderPairs): Boolean =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import util.Spans._
import util.SourceFile
import ast.{TreeTypeMap, Trees, tpd, untpd}
import Trees._
import Decorators.{given _}
import Decorators._
import transform.SymUtils._

import dotty.tools.tasty.{TastyBuffer, TastyReader}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -596,9 +596,9 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
else tp1
if (denot.isConstructor) addConstructorTypeParams(denot)
if (atEnd)
assert(!denot.isSuperAccessor, denot)
assert(!denot.symbol.isSuperAccessor, denot)
else {
assert(denot.is(ParamAccessor) || denot.isSuperAccessor, denot)
assert(denot.is(ParamAccessor) || denot.symbol.isSuperAccessor, denot)
def disambiguate(alt: Symbol) = // !!! DEBUG
trace.onDebug(s"disambiguating ${denot.info} =:= ${denot.owner.thisType.memberInfo(alt)} ${denot.owner}") {
denot.info matches denot.owner.thisType.memberInfo(alt)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/interactive/Completion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import dotty.tools.dotc.ast.untpd
import dotty.tools.dotc.config.Printers.interactiv
import dotty.tools.dotc.core.Contexts._
import dotty.tools.dotc.core.CheckRealizable
import dotty.tools.dotc.core.Decorators.StringInterpolators
import dotty.tools.dotc.core.Decorators._
import dotty.tools.dotc.core.Denotations.SingleDenotation
import dotty.tools.dotc.core.Flags._
import dotty.tools.dotc.core.Names.{Name, TermName}
import dotty.tools.dotc.core.NameKinds.SimpleNameKind
import dotty.tools.dotc.core.NameOps.NameDecorator
import dotty.tools.dotc.core.NameOps._
import dotty.tools.dotc.core.Symbols.{NoSymbol, Symbol, defn}
import dotty.tools.dotc.core.Scopes
import dotty.tools.dotc.core.StdNames.{nme, tpnme}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import ast.{NavigateAST, Trees, tpd, untpd}
import core._
import Decorators._, ContextOps._
import Contexts._, Flags._, Names._, NameOps._, Symbols._, Trees._, Types._
import transform.SymUtils.decorateSymbol
import transform.SymUtils._
import util.Spans._, util.SourceFile, util.SourcePosition
import core.Denotations.SingleDenotation
import NameKinds.SimpleNameKind
Expand Down
3 changes: 1 addition & 2 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,11 @@ object Parsers {
val Spliced = 2
}

private implicit class AddDeco(val buf: ListBuffer[Tree]) extends AnyVal {
extension (buf: ListBuffer[Tree]):
def +++=(x: Tree) = x match {
case x: Thicket => buf ++= x.trees
case x => buf += x
}
}

/** The parse starting point depends on whether the source file is self-contained:
* if not, the AST will be supplemented.
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/printing/Texts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ object Texts {
/** The given texts `xs`, each on a separate line */
def lines(xs: Traversable[Text]): Vertical = Vertical(xs.toList.reverse)

implicit class textDeco(text: => Text) {
extension (text: => Text):
def provided(cond: Boolean): Text = if (cond) text else Str("")
}

}

case class Str(s: String, lineRange: LineRange = EmptyLineRange) extends Text {
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/printing/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ package object printing {
val XprintMode: Key[Unit] = new Key

/** @pre `nel` is non-empty list */
private[printing] implicit class ListOps[A](val nel: List[A]) extends AnyVal {
def intersperse(a: A): List[A] =
extension [A](nel: List[A]):
private[printing] def intersperse(a: A): List[A] =
nel.flatMap(a :: _ :: Nil).tail
}

}
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/reporting/Reporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package reporting
import scala.annotation.internal.sharable

import core.Contexts._
import core.Decorators.PhaseListDecorator
import core.Decorators._
import collection.mutable
import core.Mode
import dotty.tools.dotc.core.Symbols.{Symbol, NoSymbol}
Expand Down
Loading