alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (Errors.scala)

This example Scala source code file (Errors.scala) is included in my "Source Code Warehouse" project. The intent of this project is to help you more easily find Scala source code examples by using tags.

All credit for the original source code belongs to scala-lang.org; I'm just trying to make examples easier to find. (For my Scala work, see my Scala examples and tutorials.)

Scala tags/keywords

applied, boolean, exprclassof, list, macro, nil, reflection, repeatedparamclass, string, symbol, type, typeref, utilities

The Errors.scala Scala example source code

package scala.reflect.macros
package compiler

import scala.compat.Platform.EOL
import scala.reflect.macros.util.Traces

trait Errors extends Traces {
  self: DefaultMacroCompiler =>

  import global._
  import analyzer._
  import definitions._
  import treeInfo._
  import typer.TyperErrorGen._
  import typer.infer.InferErrorGen._
  import runDefinitions._
  def globalSettings = global.settings

  private def implRefError(message: String) = {
    val Applied(culprit, _, _) = macroDdef.rhs
    abort(culprit.pos, message)
  }

  private def bundleRefError(message: String) = {
    val Applied(core, _, _) = macroDdef.rhs
    val culprit = core match {
      case Select(Applied(core, _, _), _) => core
      case _ => core
    }
    abort(culprit.pos, message)
  }

  def MacroImplAmbiguousError() = implRefError(
    "macro implementation reference is ambiguous: makes sense both as\n"+
    "a macro bundle method reference and a vanilla object method reference")

  def MacroBundleNonStaticError() = bundleRefError("macro bundles must be static")

  def MacroBundleWrongShapeError() = bundleRefError("macro bundles must be concrete monomorphic classes having a single constructor with a `val c: Context` parameter")

  trait Error {
    self: MacroImplRefCompiler =>

    // sanity check errors

    def MacroImplReferenceWrongShapeError() = implRefError(
      "macro implementation reference has wrong shape. required:\n"+
      "macro [<static object>].<method name>[[<type args>]] or\n" +
      "macro [<macro bundle>].<method name>[[<type args>]]")

    def MacroImplWrongNumberOfTypeArgumentsError() = {
      val diagnostic = if (macroImpl.typeParams.length > targs.length) "has too few type arguments" else "has too many arguments"
      implRefError(s"macro implementation reference $diagnostic for " + treeSymTypeMsg(macroImplRef))
    }

    private def macroImplementationWording =
      if (isImplBundle) "bundle implementation"
      else "macro implementation"

    def MacroImplNotPublicError() = implRefError(s"${macroImplementationWording} must be public")

    def MacroImplOverloadedError() = implRefError(s"${macroImplementationWording} cannot be overloaded")

    def MacroImplNonTagImplicitParameters(params: List[Symbol]) = implRefError(s"${macroImplementationWording}s cannot have implicit parameters other than WeakTypeTag evidences")

    // compatibility errors

    // helpers

    private def lengthMsg(flavor: String, violation: String, extra: Symbol) = {
      val noun = if (flavor == "value") "parameter" else "type parameter"
      val message = noun + " lists have different length, " + violation + " extra " + noun
      val suffix = if (extra ne NoSymbol) " " + extra.defString else ""
      message + suffix
    }

    private def abbreviateCoreAliases(s: String): String = {
      val coreAliases = List("WeakTypeTag", "Expr", "Tree")
      coreAliases.foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x))
    }

    private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean, untype: Boolean) = {
      def preprocess(tpe: Type) = if (untype) untypeMetalevel(tpe) else tpe
      var pssPart = (pss map (ps => ps map (p => p.defStringSeenAs(preprocess(p.info))) mkString ("(", ", ", ")"))).mkString
      if (abbreviate) pssPart = abbreviateCoreAliases(pssPart)
      var retPart = preprocess(restpe).toString
      if (abbreviate || macroDdef.tpt.tpe == null) retPart = abbreviateCoreAliases(retPart)
      pssPart + ": " + retPart
    }

    // not exactly an error generator, but very related
    // and I dearly wanted to push it away from Macros.scala
    private def checkConforms(slot: String, rtpe: Type, atpe: Type) = {
      val verbose = macroDebugVerbose

      def check(rtpe: Type, atpe: Type): Boolean = {
        def success() = { if (verbose) println(rtpe + " <: " + atpe + "?" + EOL + "true"); true }
        (rtpe, atpe) match {
          case _ if rtpe eq atpe => success()
          case (TypeRef(_, RepeatedParamClass, rtpe :: Nil), TypeRef(_, RepeatedParamClass, atpe :: Nil)) => check(rtpe, atpe)
          case (ExprClassOf(_), TreeType()) if rtpe.prefix =:= atpe.prefix => success()
          case (SubtreeType(), ExprClassOf(_)) if rtpe.prefix =:= atpe.prefix => success()
          case _ => rtpe <:< atpe
        }
      }

      val ok =
        if (verbose) withTypesExplained(check(rtpe, atpe))
        else check(rtpe, atpe)
      if (!ok) {
        if (!verbose) explainTypes(rtpe, atpe)
        val msg = {
          val ss = Seq(rtpe, atpe) map (this abbreviateCoreAliases _.toString)
          s"type mismatch for $slot: ${ss(0)} does not conform to ${ss(1)}"
        }
        compatibilityError(msg)
      }
    }

    private def compatibilityError(message: String) =
      implRefError(
        s"${macroImplementationWording} has incompatible shape:"+
        "\n required: " + showMeth(rparamss, rret, abbreviate = true, untype = false) +
        "\n or      : " + showMeth(rparamss, rret, abbreviate = true, untype = true) +
        "\n found   : " + showMeth(aparamss, aret, abbreviate = false, untype = false) +
        "\n" + message)

    def MacroImplParamssMismatchError() = compatibilityError("number of parameter sections differ")

    def MacroImplExtraParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(lengthMsg("value", "found", aparams(rparams.length)))

    def MacroImplMissingParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(abbreviateCoreAliases(lengthMsg("value", "required", rparams(aparams.length))))

    def checkMacroImplParamTypeMismatch(atpe: Type, rparam: Symbol) = checkConforms("parameter " + rparam.name, rparam.tpe, atpe)

    def checkMacroImplResultTypeMismatch(atpe: Type, rret: Type) = checkConforms("return type", atpe, rret)

    def MacroImplParamNameMismatchError(aparam: Symbol, rparam: Symbol) = compatibilityError("parameter names differ: " + rparam.name + " != " + aparam.name)

    def MacroImplVarargMismatchError(aparam: Symbol, rparam: Symbol) = {
      def fail(paramName: Name) = compatibilityError("types incompatible for parameter " + paramName + ": corresponding is not a vararg parameter")
      if (isRepeated(rparam) && !isRepeated(aparam)) fail(rparam.name)
      if (!isRepeated(rparam) && isRepeated(aparam)) fail(aparam.name)
    }

    def MacroImplTargMismatchError(atargs: List[Type], atparams: List[Symbol]) =
      compatibilityError(NotWithinBoundsErrorMessage("", atargs, atparams, macroDebugVerbose || settings.explaintypes.value))

    def MacroImplTparamInstantiationError(atparams: List[Symbol], e: NoInstance) = {
      val badps = atparams map (_.defString) mkString ", "
      compatibilityError(f"type parameters $badps cannot be instantiated%n${e.getMessage}")
    }
  }
}

Other Scala source code examples

Here is a short list of links related to this Scala Errors.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.