All Downloads are FREE. Search and download functionalities are using the official Maven repository.

parsley.debugger.internal.Rename.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2020 Parsley Contributors 
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
package parsley.debugger.internal

import scala.collection.mutable

import org.typelevel.scalaccompat.annotation.unused
import parsley.internal.deepembedding.frontend.LazyParsley
import parsley.internal.deepembedding.frontend.debugger.Debugged

// An object with a single public apply method that allows the renaming of a
// debugged  parser's name in order to increase the clarity of the debugger's
// results. By default, this does nothing other than get the prettified names of
// a parser's class defined within.
// It also requires user interaction, as it needs to collect information from the
// classes or objects that define their parser.
private [parsley] object Rename {
    // This will attempt to match parsers referentially.
    // This also assumes that all parsers are present (lazy or otherwise) before debugging.
    // Populating this map is only possible if the platform contains some form of implementation for
    // parsley.debugger.util.Collector.names, which attempts to collect the name-in-code for a given
    // reference to a parser.
    // Alternatively, users can use the `named` combinator from the debugger to weakly assign names
    // to their parsers, or directly invoke Collector.assignName to strongly assign names to parsers.
    // Just like parser reference collection for the debugger, we need a weak map so ephemeral renamed
    // parsers don't leak memory.
    lazy private val collected: mutable.Map[LazyParsley[_], String] = new XWeakMap

    // Compatibility for Scala 2.12, and for convenience within the debugger for things to do with maps.
    private [debugger] implicit class MapAddAll[K, V](mutMap: mutable.Map[K, V]) {
        def addAllFrom(collection: Map[K, V]): Unit =
            collection.foreach { case (k, v) => mutMap(k) = v }
    }

    // This method attempts the renaming of a parser, even if at least partially.
    def apply(optName: Option[String], p: LazyParsley[_]): String = {
        val defaultName = partial(p)

        val extracted = p match {
            case dbg: Debugged[_] => dbg.origin
            case _                => p
        }

        // This renames the parser if it is present, otherwise gives the default name found earlier.
        optName.getOrElse(collected.getOrElse(extracted, defaultName))
    }

    // Perform the first step of renaming, a partial rename where only the type name is exposed.
    @inline def partial(p: LazyParsley[_]): String =
        p match {
            // $COVERAGE-OFF$
            case dbg: Debugged[_] => dbg.origin.prettyName // Ideally this case isn't hit at all.
            case _ => p.prettyName
            // $COVERAGE-ON$
        }

    private [parsley] def addNames(names: Map[LazyParsley[_], String]): Unit =
        collected.addAllFrom(names)

    // $COVERAGE-OFF$
    private [parsley] def addNames(names: Iterable[(LazyParsley[_], String)]): Unit =
        names.foreach { case (k, v) => collected(k) = v }
    // $COVERAGE-ON$

    private [parsley] def addName(par: LazyParsley[_], name: String): Unit = {
        val _ = collected.put(par, name): @unused
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy