diff options
author | VladimirNik <vladimir.nikolaev9@gmail.com> | 2014-02-14 10:12:07 +0400 |
---|---|---|
committer | VladimirNik <vladimir.nikolaev9@gmail.com> | 2014-02-20 01:23:26 +0400 |
commit | 109774b0ba8f088c4b4ae503df66a23ce0869cba (patch) | |
tree | 456c90c7cd55c461932c76861b9cbf455f6cf794 | |
parent | e727314d6031aab6bb7abfded9de27ff704dcd60 (diff) | |
download | scala-109774b0ba8f088c4b4ae503df66a23ce0869cba.tar.gz scala-109774b0ba8f088c4b4ae503df66a23ce0869cba.tar.bz2 scala-109774b0ba8f088c4b4ae503df66a23ce0869cba.zip |
CodePrinter: TypedTreePrinter merged with ParsedTreePrinter
-rw-r--r-- | src/reflect/scala/reflect/internal/Printers.scala | 212 |
1 files changed, 89 insertions, 123 deletions
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index 0cf7987b4b..a45b401902 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -531,8 +531,8 @@ trait Printers extends api.Printers { self: SymbolTable => } } - // it's the printer for trees after parser and before typer phases - class ParsedTreePrinter(out: PrintWriter) extends TreePrinter(out) { + // it's the printer for AST-based code generation + class CodePrinter(out: PrintWriter, printRootPkg: Boolean) extends TreePrinter(out) { protected val parentsStack = scala.collection.mutable.Stack[Tree]() protected def currentTree = if (parentsStack.nonEmpty) Some(parentsStack.top) else None @@ -588,10 +588,21 @@ trait Printers extends api.Printers { self: SymbolTable => case Select(qual, name) if name.isTermName => s"${resolveSelect(qual)}.${printedName(name)}" case Select(qual, name) if name.isTypeName => s"${resolveSelect(qual)}#${blankForOperatorName(name)}%${printedName(name)}" case Ident(name) => printedName(name) - case _ => render(t, new ParsedTreePrinter(_)) + case _ => render(t, new CodePrinter(_, printRootPkg)) } } + protected def emptyTree(tree: Tree) = tree match { + case EmptyTree | build.SyntacticEmptyTypeTree() => true + case _ => false + } + + protected def originalTypeTrees(trees: List[Tree]) = + trees.filter(!emptyTree(_)) map { + case tt: TypeTree => tt.original + case tree => tree + } + val defaultClasses = List(tpnme.AnyRef) val defaultTraitsForCase = List(tpnme.Product, tpnme.Serializable) protected def removeDefaultTypesFromList(trees: List[Tree])(classesToRemove: List[Name] = defaultClasses)(traitsToRemove: List[Name]) = { @@ -608,11 +619,26 @@ trait Printers extends api.Printers { self: SymbolTable => removeDefaultTraitsFromList(removeDefaultClassesFromList(trees, classesToRemove), traitsToRemove) } - protected def removeDefaultClassesFromList(trees: List[Tree], classesToRemove: List[Name] = defaultClasses) = trees filter { - case Select(Ident(sc), name) => !(classesToRemove.contains(name) && sc == nme.scala_) - case _ => true - } + protected def removeDefaultClassesFromList(trees: List[Tree], classesToRemove: List[Name] = defaultClasses) = + originalTypeTrees(trees) filter { + case Select(Ident(sc), name) => !(classesToRemove.contains(name) && sc == nme.scala_) + case _ => true + } + + protected def syntheticToRemove(tree: Tree) = + tree match { + case _: ValDef | _: TypeDef => false // don't remove ValDef and TypeDef + case md: MemberDef if md.mods.isSynthetic => true + case _ => false + } + override def printOpt(prefix: String, tree: Tree) = + if (!emptyTree(tree)) super.printOpt(prefix, tree) + + override def printColumn(ts: List[Tree], start: String, sep: String, end: String) = { + super.printColumn(ts.filter(!syntheticToRemove(_)), start, sep, end) + } + def printFlags(mods: Modifiers, primaryCtorParam: Boolean = false): Unit = { val base = AccessFlags | OVERRIDE | ABSTRACT | FINAL | SEALED | LAZY val mask = if (primaryCtorParam) base else base | IMPLICIT @@ -698,6 +724,9 @@ trait Printers extends api.Printers { self: SymbolTable => def processTreePrinting(tree: Tree): Unit = { tree match { + // don't remove synthetic ValDef/TypeDef + case _ if syntheticToRemove(tree) => + case cl @ ClassDef(mods, name, tparams, impl) => if (mods.isJavaDefined) super.printTree(cl) printAnnotations(cl) @@ -916,12 +945,24 @@ trait Printers extends api.Printers { self: SymbolTable => printFunction(f)(printValueParams(vparams, inParentheses = printParentheses)) case Typed(expr, tp) => + def printTp = print("(", tp, ")") + tp match { + case EmptyTree | build.SyntacticEmptyTypeTree() => printTp + // case for untypechecked trees + case Annotated(annot, arg) if (expr ne null) && (arg ne null) && expr.equalsStructure(arg) => printTp // remove double arg - 5: 5: @unchecked + case tt: TypeTree if tt.original.isInstanceOf[Annotated] => printTp case Function(List(), EmptyTree) => print("(", expr, " _)") //func _ // parentheses required when (a match {}) : Type case _ => print("((", expr, "): ", tp, ")") } + // print only fun when targs are TypeTrees with empty original + case TypeApply(fun, targs) => + if (targs.exists(emptyTree(_))) { + print(fun) + } else super.printTree(tree) + case Apply(fun, vargs) => tree match { // processing methods ending on colons (x \: list) @@ -934,20 +975,48 @@ trait Printers extends api.Printers { self: SymbolTable => case _ => super.printTree(tree) } + case UnApply(fun, args) => + fun match { + case treeInfo.Unapplied(body) => + body match { + case Select(qual, name) if name == nme.unapply => print(qual) + case TypeApply(Select(qual, name), args) if name == nme.unapply || name == nme.unapplySeq => + print(TypeApply(qual, args)) + case _ => print(body) + } + case _ => print(fun) + } + printRow(args, "(", ", ", ")") + case st @ Super(This(qual), mix) => - printSuper(st, printedName(qual)) + printSuper(st, printedName(qual), checkSymbol = false) case th @ This(qual) => - printThis(th, printedName(qual)) - + if (tree.hasExistingSymbol && tree.symbol.isPackage) print(tree.symbol.fullName) + else printThis(th, printedName(qual)) + + // remove this.this from constructor invocation + case Select(This(_), name @ nme.CONSTRUCTOR) => print(printedName(name)) + case Select(qual: New, name) => print(qual) - - case Select(qualifier, name) => { - val printParentheses = needsParentheses(qualifier)(insideAnnotated = false) || isIntLitWithDecodedOp(qualifier, name) - if (printParentheses) print("(", resolveSelect(qualifier), ").", printedName(name)) - else print(resolveSelect(qualifier), ".", printedName(name)) - } + + case Select(qual, name) => + def checkRootPackage(tr: Tree): Boolean = + (currentParent match { //check that Select is not for package def name + case Some(_: PackageDef) => false + case _ => true + }) && (tr match { // check that Select contains package + case Select(q, _) => checkRootPackage(q) + case _: Ident | _: This => val sym = tr.symbol + tr.hasExistingSymbol && sym.isPackage && sym.name != nme.ROOTPKG + case _ => false + }) + + if (printRootPkg && checkRootPackage(tree)) print(s"${printedName(nme.ROOTPKG)}.") + val printParentheses = needsParentheses(qual)(insideAnnotated = false) || isIntLitWithDecodedOp(qual, name) + if (printParentheses) print("(", resolveSelect(qual), ").", printedName(name)) + else print(resolveSelect(qual), ".", printedName(name)) case id @ Ident(name) => if (name.nonEmpty) { @@ -987,6 +1056,9 @@ trait Printers extends api.Printers { self: SymbolTable => case SelectFromTypeTree(qualifier, selector) => print("(", qualifier, ")#", blankForOperatorName(selector), printedName(selector)) + case tt: TypeTree => + if (!emptyTree(tt)) print(tt.original) + case AppliedTypeTree(tp, args) => // it's possible to have (=> String) => String type but Function1[=> String, String] is not correct val containsByNameTypeParam = args exists treeInfo.isByNameParamType @@ -1014,119 +1086,13 @@ trait Printers extends api.Printers { self: SymbolTable => } } } - - // it's the printer for trees after typer phases - class TypedTreePrinter(out: PrintWriter, printRootPkg: Boolean) extends ParsedTreePrinter(out) { - override def printOpt(prefix: String, tree: Tree) = - if (!emptyTree(tree)) super.printOpt(prefix, tree) - - def syntheticToRemove(tree: Tree) = - tree match { - case _: ValDef | _: TypeDef => false // don't remove ValDef and TypeDef - case md: MemberDef if md.mods.isSynthetic => true - case _ => false - } - - override def printColumn(ts: List[Tree], start: String, sep: String, end: String) = { - super.printColumn(ts.filter(!syntheticToRemove(_)), start, sep, end) - } - - protected def emptyTree(tree: Tree) = tree match { - case EmptyTree | build.SyntacticEmptyTypeTree() => true - case _ => false - } - - def originalTypeTrees(trees: List[Tree]) = - trees.filter(!emptyTree(_)) map { - case tt: TypeTree => tt.original - case tree => tree - } - - override protected def removeDefaultClassesFromList(trees: List[Tree], classesToRemove: List[Name] = defaultClasses) = - super.removeDefaultClassesFromList(originalTypeTrees(trees), classesToRemove) - - override def resolveSelect(t: Tree): String = { - t match { - case _: Select | _: Ident => super.resolveSelect(t) - case _ => render(t, new TypedTreePrinter(_, printRootPkg)) - } - } - - override def processTreePrinting(tree: Tree): Unit = { - tree match { - // don't remove synthetic ValDef/TypeDef - case _ if syntheticToRemove(tree) => - - case tt: TypeTree => - if (!emptyTree(tt)) print(tt.original) - - // print only fun when targs are TypeTrees with empty original - case TypeApply(fun, targs) => - if (targs.exists(emptyTree(_))) { - print(fun) - } else super.processTreePrinting(tree) - - case UnApply(fun, args) => - fun match { - case treeInfo.Unapplied(body) => - body match { - case Select(qual, name) if name == nme.unapply => print(qual) - case TypeApply(Select(qual, name), args) if name == nme.unapply || name == nme.unapplySeq => - print(TypeApply(qual, args)) - case _ => print(body) - } - case _ => print(fun) - } - printRow(args, "(", ", ", ")") - - // remove this.this from constructor invocation - case Select(This(_), name @ nme.CONSTRUCTOR) => print(printedName(name)) - - case Select(qual, name) => - def checkRootPackage(tr: Tree): Boolean = - (currentParent match { //check that Select is not for package def name - case Some(_: PackageDef) => false - case _ => true - }) && (tr match { // check that Select contains package - case Select(q, _) => checkRootPackage(q) - case _: Ident | _: This => val sym = tr.symbol - tr.hasExistingSymbol && sym.isPackage && sym.name != nme.ROOTPKG - case _ => false - }) - - if (printRootPkg && checkRootPackage(tree)) print(s"${printedName(nme.ROOTPKG)}.") - super.processTreePrinting(tree) - - case Typed(expr, tp) => - def printTp = print("(", tp, ")") - - tp match { - case EmptyTree | build.SyntacticEmptyTypeTree() => printTp - // case for untypechecked trees - case Annotated(annot, arg) if (expr ne null) && (arg ne null) && expr.equalsStructure(arg) => printTp //to remove double arg - 5: 5: @unchecked - case tt: TypeTree if tt.original.isInstanceOf[Annotated] => printTp - case _ => super.processTreePrinting(tree) - } - - case This(qual) => - // todo: add symbol checking for common printer - if (tree.hasExistingSymbol && tree.symbol.isPackage) print(tree.symbol.fullName) - else super.processTreePrinting(tree) - - case st @ Super(th @ This(qual), mix) => - printSuper(st, printedName(qual), checkSymbol = false) - - case tree => super.processTreePrinting(tree) - } - } - } /** Hook for extensions */ def xprintTree(treePrinter: TreePrinter, tree: Tree) = treePrinter.print(tree.productPrefix+tree.productIterator.mkString("(", ", ", ")")) def newCodePrinter(writer: PrintWriter, tree: Tree, printRootPkg: Boolean): TreePrinter = - new TypedTreePrinter(writer, printRootPkg) + new CodePrinter(writer, printRootPkg) def newTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer) def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream)) |