I guess it's so darn topical, I have to ask. Can you look at my two candidates for being "analyzer plugins"? I speak of course of interactive and scaladoc. This is not proud code, but it does encapsulate all the little bits which used to be scattered hither and thither with "forScaladoc" and "forInteractive" guards.

My question is, would either of these be able to use the "AnalyzerPlugins" framework to do what they do?
```
trait InteractiveAnalyzer extends Analyzer {
  val global : Global
  import global._

  override def newTyper(context: Context): InteractiveTyper = new InteractiveTyper(context)
  override def newNamer(context: Context): InteractiveNamer = new InteractiveNamer(context)
  override protected def newPatternMatching = false

  class InteractiveTyper(context0: Context) extends Typer(context0) {
    override def canAdaptConstantTypeToLiteral = false
    override def canTranslateEmptyListToNil    = false
    override def missingSelectErrorTree(tree: Tree, qual: Tree, name: Name): Tree = tree match {
      case Select(_, _)             => treeCopy.Select(tree, qual, name)
      case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name)
    }
  }

  class InteractiveNamer(context0: Context) extends Namer(context0) {
    override def saveDefaultGetter(meth: Symbol, default: Symbol) {
      // save the default getters as attachments in the method symbol. if compiling the
      // same local block several times (which can happen in interactive mode) we might
      // otherwise not find the default symbol, because the second time it the method
      // symbol will be re-entered in the scope but the default parameter will not.
      meth.attachments.get[DefaultsOfLocalMethodAttachment] match {
        case Some(att) => att.defaultGetters += default
        case None      => meth.updateAttachment(new DefaultsOfLocalMethodAttachment(default))
      }
    }
    // this logic is needed in case typer was interrupted half
    // way through and then comes back to do the tree again. In
    // that case the definitions that were already attributed as
    // well as any default parameters of such methods need to be
    // re-entered in the current scope.
    override def enterExistingSym(sym: Symbol): Context = {
      if (sym != null && sym.owner.isTerm) {
        enterIfNotThere(sym)
        if (sym.isLazy)
          sym.lazyAccessor andAlso enterIfNotThere

        for (defAtt <- sym.attachments.get[DefaultsOfLocalMethodAttachment])
          defAtt.defaultGetters foreach enterIfNotThere
      }
      super.enterExistingSym(sym)
    }
    override def enterIfNotThere(sym: Symbol) {
      val scope = context.scope
      @tailrec def search(e: ScopeEntry) {
        if ((e eq null) || (e.owner ne scope))
          scope enter sym
        else if (e.sym ne sym)  // otherwise, aborts since we found sym
          search(e.tail)
      }
      search(scope lookupEntry sym.name)
    }
  }
}
```

```
trait ScaladocAnalyzer extends Analyzer {
  val global : ScaladocGlobal
  import global._

  override def newTyper(context: Context): ScaladocTyper = new ScaladocTyper(context)

  class ScaladocTyper(context0: Context) extends Typer(context0) {
    private def unit = context.unit

    override def canAdaptConstantTypeToLiteral = false

    override def typedDocDef(docDef: DocDef, mode: Mode, pt: Type): Tree = {
      val sym = docDef.symbol

      if ((sym ne null) && (sym ne NoSymbol)) {
        val comment = docDef.comment
        docComments(sym) = comment
        comment.defineVariables(sym)
        val typer1 = newTyper(context.makeNewScope(docDef, context.owner))
        for (useCase <- comment.useCases) {
          typer1.silent(_ => typer1 defineUseCases useCase) match {
            case SilentTypeError(err) =>
              unit.warning(useCase.pos, err.errMsg)
            case _ =>
          }
          for (useCaseSym <- useCase.defined) {
            if (sym.name != useCaseSym.name)
              unit.warning(useCase.pos, "@usecase " + useCaseSym.name.decode + " does not match commented symbol: " + sym.name.decode)
          }
        }
      }

      super.typedDocDef(docDef, mode, pt)
    }

    def defineUseCases(useCase: UseCase): List[Symbol] = {
      def stringParser(str: String): syntaxAnalyzer.Parser = {
        val file = new BatchSourceFile(context.unit.source.file, str) {
          override def positionInUltimateSource(pos: Position) = {
            pos.withSource(context.unit.source, useCase.pos.start)
          }
        }
        newUnitParser(new CompilationUnit(file))
      }

      val trees = stringParser(useCase.body+";").nonLocalDefOrDcl
      val enclClass = context.enclClass.owner

      def defineAlias(name: Name) = (
        if (context.scope.lookup(name) == NoSymbol) {
          lookupVariable(name.toString.substring(1), enclClass) foreach { repl =>
            silent(_.typedTypeConstructor(stringParser(repl).typ())) map { tpt =>
              val alias = enclClass.newAliasType(name.toTypeName, useCase.pos)
              val tparams = cloneSymbolsAtOwner(tpt.tpe.typeSymbol.typeParams, alias)
              val newInfo = genPolyType(tparams, appliedType(tpt.tpe, tparams map (_.tpe)))
              alias setInfo newInfo
              context.scope.enter(alias)
            }
          }
        }
      )

      for (tree <- trees; t <- tree)
        t match {
          case Ident(name) if name startsWith '$' => defineAlias(name)
          case _ =>
        }

      useCase.aliases = context.scope.toList
      namer.enterSyms(trees)
      typedStats(trees, NoSymbol)
      useCase.defined = context.scope.toList filterNot (useCase.aliases contains _)

      if (settings.debug.value)
        useCase.defined foreach (sym => println("defined use cases: %s:%s".format(sym, sym.tpe)))

      useCase.defined
    }
  }
}
```