ca52f554a1/org.scala-refactoring.library/src/test/scala/scala/tools/refactoring/tests/sourcegen/IndividualSourceGenTest.scala

User picture

Commiter: Mirko Stocker

Author: Mirko Stocker

Revision: ca52f554a1


File Size: 46.4 KB

(19 Jan 08:36 UTC) 4 months ago

Fix compilation errors on 2.10 related to Names.

 

Showing without highlighting since it looks like a big file and may slow your browser - show with highlighting

Show/hide line numbers
/*
 * Copyright 2005-2010 LAMP/EPFL
 */

package scala.tools.refactoring
package tests.sourcegen

import tests.util.TestHelper
import org.junit.Assert
import org.junit.Assert._
import sourcegen.SourceGenerator
import common.{SilentTracing, ConsoleTracing, Change}
import tools.nsc.symtab.Flags
import tools.nsc.ast.parser.Tokens

class IndividualSourceGenTest extends TestHelper with SourceGenerator with SilentTracing with transformation.TreeFactory {
  
  import global._
  
  override def treeForFile(file: AbstractFile) = {
    unitOfFile get file map (_.body) flatMap removeAuxiliaryTrees
  }
    
  def generateText(t: Tree): String = generate(t, sourceFile = Some(t.pos.source)).asText
  
  implicit def treeToPrettyPrint(original: Tree) = new {
    def cleanTree(t: Tree) = (removeAuxiliaryTrees &> emptyAllPositions)(t).get
    def prettyPrintsTo(expected: String) = assertEquals(expected, generateText(cleanTree(original)))
  }
  
  def getFirstMethod(source: String) = treeFrom(source) match {
    case PackageDef(_, ClassDef(_, _, _, Template(_, _, (d: DefDef) :: _)) :: _) => d
    case _ => Assert.fail(); throw new Exception("unreachable")
  }
  
  def testDefDefWithNoPositionAndOriginalPosition(src: String, exp1: String, exp2: String) {
    
    val originalDefDef = getFirstMethod(src)
    
    val newDefDef = originalDefDef.copy()
        
    assertEquals(exp1, generate(removeAuxiliaryTrees apply newDefDef get, sourceFile = Some(originalDefDef.pos.source)).asText)

    newDefDef.setPos(originalDefDef.pos)
    
    assertEquals(exp2, generate(removeAuxiliaryTrees apply newDefDef get, sourceFile = Some(originalDefDef.pos.source)).asText)    
  }
  
  @Test
  def testNewDefDefWithOriginalContent1() = {
    
    testDefDefWithNoPositionAndOriginalPosition(
    """
    trait A {
      def someMethod: Unit
    }
    """, 
    """def someMethod: Unit {
}""", 
    """
      def someMethod: Unit""")
  }
  
  @Test
  def testNewDefDefWithOriginalContent2() = {
    
    testDefDefWithNoPositionAndOriginalPosition(
    """
    trait A {
      def someMethod(): String
    }
    """, 
    """def someMethod(): String {
}""", 
    """
      def someMethod(): String""")
  }
  
  @Test
  def testNewDefDefWithOriginalContent3() = {
    
    testDefDefWithNoPositionAndOriginalPosition(
    """
    trait A {
      def someMethod[T](): T
    }
    """, 
    """def someMethod[T](): T {
}""", 
    """
      def someMethod[T](): T""")
  }
  
  @Test
  def testNewDefDefWithOriginalContent4() = {
    
    testDefDefWithNoPositionAndOriginalPosition(
    """
    trait A {
      protected def someMethod[T](param1: Int, param2: T)(param3: => T)
    }
    """, 
    """protected def someMethod[T](param1: Int, param2: T)(param3: => T) {
}""", 
    """
      protected def someMethod[T](param1: Int, param2: T)(param3: => T)""")
  }
  
  @Test
  def selfTypeAnnotation {
    val src = """
trait tr[A] {
  self: List[A] => 
  
  def asd() {
  }
}
"""
    val ast = treeFrom(src)    
    val defdef = mkDefDef(name = "member", body = List(Ident(newTermName("()"))))
    
    val transformedAst = topdown {
      matchingChildren {
        transform {
          case t: Template => t.copy(body = t.body ::: List(defdef)) setPos t.pos
        }
      }
    } apply ast
    
    assertEquals("""
trait tr[A] {
  self: List[A] => 
  
  def asd() {
  }
  
  def member() = {
    ()
  }
}
""", common.Change.applyChanges(refactor(transformedAst.toList), src))
  }
  
  @Test
  def addMethodToEmptyTraitWithSelfTypeAnnotation {
    val src = """
trait tr[A] {
  self: List[A] => 

}
"""
    val ast = treeFrom(src)
    
    val defdef = mkDefDef(name = "member", body = List(Ident(newTermName("()"))))
    
    val transformedAst = topdown {
      matchingChildren {
        transform {
          case t: Template => t.copy(body = t.body ::: List(defdef)) setPos t.pos
        }
      }
    } apply ast
    
    assertEquals("""
trait tr[A] {
  self: List[A] => 
  def member() = {
    ()
  }

}
""", common.Change.applyChanges(refactor(transformedAst.toList), src))
  }
  
  @Test
  def misprintedFunctionDefinition {
        
    val ast = treeFrom("""
      package generated

      object primitive {

        def member[A](a: A, li: KIVList[A]): Boolean = {
          if (li.emptyp) false
          else {
            (a equals li.car) || member(a, li.cdr)
          }
        }
      }
    """)
    
    val transformedAst = topdown {
      matchingChildren {
        transform {
          case t: DefDef => t.copy()
        }
      }
    } apply ast

    val changes = refactor(transformedAst.toList)
    assertEquals("""if (li.emptyp) false
else {
  (a equals li.car) || member(a, li.cdr)
""", changes.head.text)
  }
  
  @Test
  def valDefRhsAlone(): Unit = {
    
    val tree = treeFrom("""
    object O {
      val a = {4 + 3  }
    }
    """)
    
    val valDef = tree match {
      case PackageDef(_, ModuleDef(_, _, Template(_, _, _ :: (v: ValDef) :: _)) :: _) => v
      case _ => Assert.fail(); emptyValDef // too bad fail does not return Nothing
    }
        
    assertEquals("""val a = {4 + 3  }""", generate(removeAuxiliaryTrees apply valDef get, sourceFile = Some(tree.pos.source)).center.asText)
          
    assertEquals("""{4 + 3  }""", generate(removeAuxiliaryTrees apply valDef.rhs get, sourceFile = Some(tree.pos.source)).asText)
          
    assertEquals(0, createChanges(List(valDef)).size)
  }
  
  @Test
  @Ignore
  def newWith(): Unit = {
    
    val ast = treeFrom("""
    class A(x: Int)
    trait B
    object AWithB {
      val ab = new A(10)
    }
    """)
    
    val transformedAst = topdown {
      matchingChildren {
        transform {
          case t: ValDef if t.name.toString == "ab " => 

            val newRhs = Block(
              mkClass(
                name = "$anon", 
                parents = Ident(newTermName("A")) :: Ident(newTermName("B")) :: Nil,
                superArgs = Literal(Constant(5)) :: Nil
              ), 
              Apply(Select(New(Ident(newTermName("$anon"))), nme.CONSTRUCTOR), Nil)
            )
            
            t.copy(rhs = newRhs)
        }
      }
    } apply ast
    
    assertEquals("""
    class A(x: Int)
    trait B
    object AWithB {
      val ab = new A(5) with B
    }
    """, generateText(transformedAst.get))
  }
  
  @Test
  def modifiedDefDef(): Unit = {
    
    val originalDefDef = treeFrom("""
    object Account {
       def amethod(v: Int, a: Account): Unit = {
         a.add(v)
       }
    }
    class Account {
       // before value
       var value = 4
       // after value
    
       def add(v: Int) {
         value += v
       }
    }
    """) match {
      case PackageDef(_, ModuleDef(_, _, Template(_, _, _ :: (v: DefDef) :: _)) :: _) => v
      case _ => Assert.fail(); Predef.error("") // too bad fail does not return Nothing
    }
    
    val newRHS1 = Apply(Select(Ident(newTermName("com")),newTermName("synchronized")), List(shallowDuplicate(originalDefDef.rhs) setPos NoPosition))
    
    val newDefDef1 = originalDefDef copy (rhs = newRHS1) setPos originalDefDef.pos
        
    assertEquals("""def amethod(v: Int, a: Account): Unit = com.synchronized(a.add(v))""", generate(removeAuxiliaryTrees apply newDefDef1 get, sourceFile = Some(originalDefDef.pos.source)).center.asText)
   
    assertEquals("""
       def amethod(v: Int, a: Account): Unit = com.synchronized(a.add(v))""", createFragment(removeAuxiliaryTrees apply newDefDef1 get).asText)
   
    val newRHS2 = Apply(Select(Ident(newTermName("com")), newTermName("synchronized")), List(originalDefDef.rhs))
    
    val newDefDef2 = originalDefDef copy (rhs = newRHS2) setPos originalDefDef.pos
        
    assertEquals("""def amethod(v: Int, a: Account): Unit = com.synchronized({
       a.add(v)
       })""", generate(removeAuxiliaryTrees apply newDefDef2 get, sourceFile = Some(originalDefDef.pos.source)).center.asText)
          
    assertEquals("""
       def amethod(v: Int, a: Account): Unit = com.synchronized({
       a.add(v)
       })""", createFragment(removeAuxiliaryTrees apply newDefDef2 get).asText)
 
       
    assertEquals(1, createChanges(List(newDefDef1)).size)
    
    assertEquals(1, createChanges(List(newDefDef2)).size)
  }
  
  @Test
  def modifiedDefDefWithFor(): Unit = {
    
    val originalDefDef = treeFrom("""
    object Account1 {
      def addInterest(accounts: Array[Account1], rate: Float) {
        for (a <- accounts) {
          println(a.value)
        }
      }
    }
    class Account1 {
       // before value
       var value = 4
       // after value
    
       def add(v: Int) {
         value += v
       }
    }
    """) match {
      case PackageDef(_, ModuleDef(_, _, Template(_, _, _ :: (v: DefDef) :: _)) :: _) => v
      case _ => Assert.fail(); Predef.error("") // too bad fail does not return Nothing
    }
    
    val newRHS1 = new Block(List(Apply(Select(Ident(newTermName("com")),newTermName("synchronized")), List(originalDefDef.rhs))), EmptyTree)
    
    val newDefDef1 = originalDefDef copy (rhs = newRHS1) setPos originalDefDef.pos
    
    assertEquals("""
      def addInterest(accounts: Array[Account1], rate: Float) {
        com.synchronized({
        for (a <- accounts) {
          println(a.value)
        }
      })
      }""", createFragment(removeAuxiliaryTrees apply newDefDef1 get).asText)

  }
  
  @Test
  def manyParentheses(): Unit = {
    
    val tree = treeFrom("""
    class VBox[T](i: Int)
    class Test {
     var box = new VBox[Int]({ 2 + 4 })
    }
    """)
      
    assertEquals("""
    class VBox[T](i: Int)
    class Test {
     var box = new VBox[Int]({ 2 + 4 })
    }
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def bracesAndComments(): Unit = {
    
    val tree = treeFrom("""
package com.megaannum.test

class Foo3 {
   // before idFoo
   private var idFoo = { 3 + 4 }
   // after idFoo

   // before getIdFoo
   def getIdFoo = idFoo
   // after getIdFoo
   def setIdFoo(id: Int) = idFoo = id
}
    """)
      
    assertEquals("""
package com.megaannum.test

class Foo3 {
   // before idFoo
   private var idFoo = { 3 + 4 }
   // after idFoo

   // before getIdFoo
   def getIdFoo = idFoo
   // after getIdFoo
   def setIdFoo(id: Int) = idFoo = id
}
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def bracesAndComments2(): Unit = {
    
    val tree = treeFrom("""
package com.megaannum.test

class Foo3 {
   // before idFoo
   private var idFoo = { 3 + 4 }
   // after idFoo
}
    """)
      
    assertEquals("""
package com.megaannum.test

class Foo3 {
   // before idFoo
   private var idFoo = { 3 + 4 }
   // after idFoo
}
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def missingDot(): Unit = {
    
    val tree = treeFrom("""
class Foo3 {
   var _idFoo = 7
   this._idFoo = 5
}
    """)
      
    assertEquals("""
class Foo3 {
   var _idFoo = 7
   this._idFoo = 5
}
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def doubledName(): Unit = {
    
    val tree = treeFrom("""
class Account2 {
   var value = 0
   def add1(v: Int) {
     value += v
   }
}
    """)
      
    assertEquals("""
class Account2 {
   var value = 0
   def add1(v: Int) {
     value += v
   }
}
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def extraParens(): Unit = {
    
    val tree = treeFrom("""
object Acco {
   def amethod(v: Int, a: Int) = 
     synchronized({
       v + a
     })
}
    """)
      
    assertEquals("""
object Acco {
   def amethod(v: Int, a: Int) = 
     synchronized({
       v + a
     })
}
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def namedArgs(): Unit = {
    
    val tree = treeFrom("""
    object NamedArguments {
      def p(i: Int, before: String, separator: String, after: String) = ()
 
      p(5, separator = ", ", before = "\\{", after = "\\}")  
    }
    """)
      
    assertEquals("""
    object NamedArguments {
      def p(i: Int, before: String, separator: String, after: String) = ()
 
      p(5, separator = ", ", before = "\\{", after = "\\}")  
    }
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def namedArg(): Unit = {
    
    val tree = treeFrom("""
    object NamedArg {
      def p(first: String, second: Int) = ()
 
      def callP = {
        p(second = 42, first = "-")
      }
    }
    """)
      
    assertEquals("""
    object NamedArg {
      def p(first: String, second: Int) = ()
 
      def callP = {
        p(second = 42, first = "-")
      }
    }
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def namedArgWithDefault(): Unit = {
    
    val tree = treeFrom("""
    object NamedArgWithDefault {
      def p(first: String = "default", second: Int) = ()
 
      def callP = {
        p(second = 42)
      }
    }
    """)
      
    assertEquals("""
    object NamedArgWithDefault {
      def p(first: String = "default", second: Int) = ()
 
      def callP = {
        p(second = 42)
      }
    }
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def patternMatch(): Unit = {
    
    val tree = treeFrom("""
    object O {
      case class ModuleDef(i: Int, s: String)

      ModuleDef(42, "foo") match {
        case ModuleDef(theI, theS) =>
//        mods.annotations map traverse
          val mods_ = theS
          mods_ + theI
      }
    }
    """)
      
    assertEquals("""
    object O {
      case class ModuleDef(i: Int, s: String)

      ModuleDef(42, "foo") match {
        case ModuleDef(theI, theS) =>
//        mods.annotations map traverse
          val mods_ = theS
          mods_ + theI
      }
    }
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def patternMatchOnTupel(): Unit = {
    
    val tree = treeFrom("""
    object O {
      (42, "foo") match {
        case (theI, theS) =>
          ()
      }
    }
    """)
      
    assertEquals("""
    object O {
      (42, "foo") match {
        case (theI, theS) =>
          ()
      }
    }
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def newObject(): Unit = {
    
    val tree = treeFrom("""
    object Foo {
       def apply() = new Foo
    }
    
    class Foo
    """)
      
    assertEquals("""
    object Foo {
       def apply() = new Foo
    }
    
    class Foo
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def newParameterizedObject(): Unit = {
    
    val tree = treeFrom("""
object Foo4 {
   def apply[T](name: String) = new Foo4[T](name)
}

class Foo4[T](name: String) {
   def echo[T](t: T):T = t
}
    """)
      
    assertEquals("""
object Foo4 {
   def apply[T](name: String) = new Foo4[T](name)
}

class Foo4[T](name: String) {
   def echo[T](t: T):T = t
}
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def newParameterizedObject2(): Unit = {
    
    val tree = treeFrom("""
object Foo5 {
   def apply() = { new Foo5 }
}
class Foo5
    """)
      
    assertEquals("""
object Foo5 {
   def apply() = { new Foo5 }
}
class Foo5
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def annotation(): Unit = {
    
    val tree = treeFrom("""
import java.lang.String

class RunWith(c: Class[_]) extends StaticAnnotation

/*(*/  /*)*/

@RunWith(classOf[String])
class Test
    """)
      
    assertEquals("""
import java.lang.String

class RunWith(c: Class[_]) extends StaticAnnotation

/*(*/  /*)*/

@RunWith(classOf[String])
class Test
    """, generateText(removeAuxiliaryTrees apply tree get))
    
    assertEquals(0, createChanges(List(tree)).size)
  }
  
  @Test
  def testFunctionArg() {
    val ast = treeFrom(
"""
class A {
def fun[A, B, C](fu: (A, B, C) => A): A
}
""")
    assertEquals("""
class A {
def fun[A, B, C](fu: (A, B, C) => A): A
}
""", generateText(ast))
  }
  
  @Test
  def testClassParameter() {
    val ast = treeFrom("""
class A(a: Int) {
}
""")
    assertEquals("""
class A(a: Int) {
}
""", generateText(ast))
    }
  
  @Test
  def testPrintParentheses() {

    val ast = treeFrom("""
    trait tr {
      def bar(s: String) = s
      def foo() {
        bar("ASD")
      }
    }
    """)

    val result = topdown {
      matchingChildren {
        transform {
          case a: Apply =>
            a.copy(args = List[Tree]()) setPos a.pos
        }
      }
    } apply (ast)

    assertEquals("""
    trait tr {
      def bar(s: String) = s
      def foo() {
        bar()
      }
    }
    """, createText(result.get, Some(ast.pos.source)))
  }
  
  @Test
  def testPrintNoParentheses() {

    val ast = treeFrom("""
    trait tr {      
      def bar(s: String) = s
      def foo() {
        bar("ASD")
      }
    }
    """)

    val result = topdown {
      matchingChildren {
        transform {
          case a: Apply => a.fun
        }
      }
    } apply (ast)

    assertEquals("""
    trait tr {      
      def bar(s: String) = s
      def foo() {
        bar
      }
    }
    """, createText(result.get, Some(ast.pos.source)))
  }

  @Test
  def replaceWithThis() {

    val str = """
    class MyList[T] {
      //transformation works correctly when parentheses are missing here 
      def emptyp() = false
    }        
    trait tr[A] {
      self: KIVList[A] =>
      def every[A1](p: (A1) => Boolean, li: MyList[A]): Boolean = {
        li.emptyp || li.emptyp
      }
    }
    """
    val ast = treeFrom(str)
    
    var valDef: ValDef = null
    topdown {
      matchingChildren {
        transform {
          case t: ValDef =>
            valDef = t
            t
        }
      }
    } apply (ast)

    val result = topdown {
      matchingChildren {
        transform {
          case d: DefDef if (d.name.toString() == "every") => d.copy() replaces d
          case t: Ident if (t.symbol == valDef.symbol) =>
            Ident(newTypeName("this")) setPos t.pos
        }
      }
    } apply (ast)


    val changes = refactor(result.toList)
    val res = common.Change.applyChanges(changes, str)
    assertEquals("""
    class MyList[T] {
      //transformation works correctly when parentheses are missing here 
      def emptyp() = false
    }        
    trait tr[A] {
      self: KIVList[A] =>
      def every[A1](p: (A1) => Boolean, li: MyList[A]): Boolean = {
        this.emptyp || this.emptyp
      }
    }
    """, res)
  }
  
    @Test
  def changeMethodInvocation() {

    val str = """
    package abc
    object primitive {
      def mapcar[A, B](fu: (A) => B, li: List[A]): List[B] = {
        
      }
      def asd() = {
        mapcar(((x: String) => x.isEmpty()), List(""))
      }
    }
    """
    val ast = treeFrom(str)

    val result = topdown {
      matchingChildren {
        transform {
          case a: Apply if (a.args.length > 1) =>
            val fun1 = Select(
              name = newTermName(a.fun.symbol.nameString),
              qualifier = a.args.last)
            a.copy(args = a.args.init, fun = fun1) replaces a
        }
      }
    } apply (ast)

    val changes = refactor(result.toList)
    val res = common.Change.applyChanges(changes, str)
    assertEquals("""
    package abc
    object primitive {
      def mapcar[A, B](fu: (A) => B, li: List[A]): List[B] = {
        
      }
      def asd() = {
        List("").mapcar((x: String) => x.isEmpty())
      }
    }
    """, res)
  }

  @Test
  def changeMethodInvocation2() {

    val src = """
    package abc
    object primitive {
      def append[A](li1: List[A], li2: List[A]) = Nil
  
      append(List("asd"), {
          val x = 1
          List("Def")
      })
      
    }
    """
    
    val ast = treeFrom(src)

    val result = topdown {
      matchingChildren {
        transform {
          case a: Apply if (a.args.length > 1) =>
            val fun1 = Select(
              name = newTermName(a.fun.symbol.nameString),
              qualifier = a.args.last)
            a.copy(args = a.args.init, fun = fun1) replaces a
        }
      }
    } apply (ast)
    
    assertEquals("""
    package abc
    object primitive {
      def append[A](li1: List[A], li2: List[A]) = Nil
  
      {
          val x = 1
          List("Def")
      }.append(List("asd"))
      
    }
    """, createText(result.get, Some(ast.pos.source)))
  }   
  
  @Test
  def testRemoveAnArgument() {

    val src = """
    trait tr {
      def remove[A](elem: A, li: List[A]): List[A] = {
        li.remove_if((x: A) => (elem equals x))
      }
    }
    """
      
    val ast = treeFrom(src)

    val result = topdown {
      matchingChildren {
        transform {
          case t: DefDef if (t.vparamss(0).size > 0) =>
            val vparamss = List(List(t.vparamss(0).head))
            t.copy(vparamss = vparamss) setPos t.pos
        }
      }
    } apply (ast)

    val changes = refactor(result.toList)

    assertEquals("""
    trait tr {
      def remove[A](elem: A): List[A] = {
        li.remove_if((x: A) => (elem equals x))
      }
    }
    """, common.Change.applyChanges(changes, src))
  }
  
   @Test
  def testParentheses() {
    val ast = treeFrom("""
    package abc
    trait tr[T] {
      def remove[A](elem: A, li: List[A]): List[A] = {
        li.remove((x: A) => (elem equals x))
      }
    }
    """)
    val result = topdown {
      matchingChildren {
        transform {
          case t: DefDef if (t.name == newTermName("remove")) =>
            t.copy() replaces t
        }
      }
    } apply (ast)

    assertEquals("""
    package abc
    trait tr[T] {
      def remove[A](elem: A, li: List[A]): List[A] = {
        li.remove((x: A) => (elem equals x))
      }
    }
    """, createText(result.get, Some(ast.pos.source)))
  }
   
   @Test
  def testFullQualifiedName() {
    val str = """
    package asd
    object primitive {
      def member[A](a:A, li:List[A]):Boolean = true
      def has_no_duplicates[A](li: List[A]): Boolean = {
        li.isEmpty || ((!member(li.head, li.tail)) && has_no_duplicates(li.tail))
      }
    }
    """
    val ast = treeFrom(str)

    val result = topdown {
      matchingChildren {
        transform {
          case t: Template =>
            t.copy(body = t.body ::: List(t.body.last)) setPos t.pos
          case t @ TypeApply(Select(name, qualifier), args) if (t.symbol.name == newTermName("member")) =>
            val s = t.symbol.fullName
            val qual = s.substring(0, s.lastIndexOf("."))
            Select(
              qualifier = Ident(name = newTypeName(qual)),
              name = t.fun.asInstanceOf[Select].name)
        }
      }
    } apply ast
    val changes = refactor(result.toList)
    val res1 = common.Change.applyChanges(changes, str)
    assertEquals("""
    package asd
    object primitive {
      def member[A](a:A, li:List[A]):Boolean = true
      def has_no_duplicates[A](li: List[A]): Boolean = {
        li.isEmpty || ((!(asd.primitive.member(li.head, li.tail))) && has_no_duplicates(li.tail))
      }
      def has_no_duplicates[A](li: List[A]): Boolean = {
        li.isEmpty || ((!(asd.primitive.member(li.head, li.tail))) && has_no_duplicates(li.tail))
      }
    }
    """, res1)
  }
   
    @Test
  def changeMethodInvocation3() {

    val ast = treeFrom("""
    package abc
    object primitive {
      def append[A](li1: List[A], li2: List[A]) = Nil
      append(List("asd")
          , List("Def"))
    }
    """)

    val result = topdown {
      matchingChildren {
        transform {

          case a: Apply if (a.args.length > 1) =>
            val buf = a.args.toBuffer
            val arg = buf(1)
            buf.remove(1)
            val fun1 = Select(
              name = newTermName(a.fun.symbol.nameString),
              qualifier = arg)
            a.copy(args = buf.toList, fun = fun1) setPos a.pos
        }
      }
    } apply (ast)

    assertEquals("""
    package abc
    object primitive {
      def append[A](li1: List[A], li2: List[A]) = Nil
      
      List("Def").append(List("asd"))
    }
    """, createText(result.get, Some(ast.pos.source)))
  }
  
  @Test
  def testCopy() {
    val str = """
    object primitive {
      def member[A](a:A, li:List[A]):Boolean = {
        def f[B](li: List[B]) = {
          true
        }
        f[A](li)
        true
      }
    }
    """
    val ast = treeFrom(str)

    val result = topdown {
      matchingChildren {
        transform {
          case t: DefDef => t.copy()
        }
      }
    } apply ast

    val changes = refactor(result.toList)
    val res1 = common.Change.applyChanges(changes, str)
    assertEquals("""
    object primitive {
      def member[A](a:A, li:List[A]):Boolean = {
        def f[B](li: List[B]) = {
        true
        }
        f[A](li)
        true
      }
    }
    """, res1)
  }
  
  @Test
  def testCopy2() {
    val str = """
    package abc
    case class Pair[A, B](a: A, b: B)
    object primitive {
      def divide[A](testpred: (A) => Boolean): Pair[List[A], List[A]] = {
        null
      }
    }
    trait tr[A] {
      self: List[A] =>
    }
    """
    val ast = treeFrom(str)
    var defdef: Tree = null

    topdown(matchingChildren(
      transform {
        case t: DefDef if (t.name == newTermName("divide")) =>
          defdef = t; t
      })) apply ast

    val res = topdown(matchingChildren(
      transform {
        case t: TypeTree if (t.nameString == "A") =>
          mkRenamedTypeTree(t, "A1", t.symbol)
        case t: TypeDef if (t.nameString == "A") =>
          mkRenamedSymTree(t, "A1")
      })) apply defdef

    val result = topdown(matchingChildren(
      transform {
        case c: ClassDef if (c.name == newTypeName("tr")) =>
          val t = c.impl
          val templ = c.impl.copy(body = t.body ::: List(res.get)) setPos t.pos
          c.copy(impl = templ) setPos c.pos
      })) apply ast

    assertEquals("""
    package abc
    case class Pair[A, B](a: A, b: B)
    object primitive {
      def divide[A](testpred: (A) => Boolean): Pair[List[A], List[A]] = {
        null
      }
    }
    trait tr[A] {
      self: List[A] =>
      def divide[A1](testpred: (A1) => Boolean): Pair[List[A1], List[A1]] = {
        null
      }
    }
    """, common.Change.applyChanges(refactor(result.toList), str))
  }
  
  @Test
  def testCopy3() {
    val str = """
    package abc
    object primitive {
      def reduce1[A1, A](fu: (A1, A) => A1, li: List[A], init: A1) = init
      def member_test[A1, B](x: A1, li: List[B], testp: (A1, B) => Boolean): Boolean = {
        reduce1((b: Boolean, xli: B) => b, li, false)
      }
    }
    trait tr[A] {
      self: List[A] =>
    }
    """
    val ast = treeFrom(str)
    var defdef: Tree = null

    topdown(matchingChildren(
      transform {
        case t: DefDef if (t.name == newTermName("member_test")) =>
          defdef = t; t
      })) apply ast

    val res = topdown(matchingChildren(
      transform {
        case t: TypeTree if (t.nameString == "B") =>
          mkRenamedTypeTree(t, "B1", t.symbol)
        case t: TypeDef if (t.nameString == "B") =>
          mkRenamedSymTree(t, "B1")
      })) apply defdef

    val result = topdown(matchingChildren(
      transform {
        case c: ClassDef if (c.name == newTypeName("tr")) =>
          val t = c.impl
          val templ = c.impl.copy(body = t.body ::: List(res.get)) setPos t.pos
          c.copy(impl = templ) setPos c.pos
      })) apply ast

    assertEquals("""
    package abc
    object primitive {
      def reduce1[A1, A](fu: (A1, A) => A1, li: List[A], init: A1) = init
      def member_test[A1, B](x: A1, li: List[B], testp: (A1, B) => Boolean): Boolean = {
        reduce1((b: Boolean, xli: B) => b, li, false)
      }
    }
    trait tr[A] {
      self: List[A] =>
      def member_test[A1, B1](x: A1, li: List[B1], testp: (A1, B1) => Boolean): Boolean = {
        reduce1((b: Boolean, xli: B1) => b, li, false)
      }
    }
    """, common.Change.applyChanges(refactor(result.toList), str))
  }
   
  @Test
  def testCopy4() {
    val str = """
    package abc
    object primitive {
      def fail() = {}
      def foo(f: Int): Boolean = {
        if((f == 0)) fail
        else false
      }
    }
    """
    val ast = treeFrom(str)

    val result = topdown(matchingChildren(
      transform {
        case t: Apply if (t.fun.nameString == "fail") => t.copy()
      })) apply ast

    assertEquals("""
    package abc
    object primitive {
      def fail() = {}
      def foo(f: Int): Boolean = {
        if((f == 0)) fail()
        else false
      }
    }
    """, common.Change.applyChanges(refactor(result.toList), str))
  }
  
  @Test
  def testCopy4Variation() {
    val str = """
    package abc
    object primitive {
      def fail() = {}
      def foo(f: Int): Boolean = {
        if((f == 0)) fail()
        else false
      }
    }
    """
    val ast = treeFrom(str)

    val result = topdown(matchingChildren(
      transform {
        case t: DefDef => t.copy()
        case t: Apply if (t.fun.nameString == "fail") =>
          val s = t.symbol.fullName
          val qual = s.substring(0, s.lastIndexOf("."))
          val select = Select(
            qualifier = Ident(name = newTypeName(qual)),
            name = t.fun.asInstanceOf[Select].name)
          t.copy(fun = select) setPos t.pos
      })) apply ast

    assertEquals("""
    package abc
    object primitive {
      def fail() = {}
      
      def foo(f: Int): Boolean = {
      if((f == 0)) abc.primitive.fail()
      else false
      }
    }
    """, common.Change.applyChanges(refactor(result.toList), str))
  }
  
  @Test
  def testCopy5() {
    val str = """
    package abc
    object primitive {
      def length[A](li:List[A]):Int = 0
      def enumerate[A](li:List[A]):List[Int] = {
        length[A](li)
      Nil
      }
    }
    trait tr[A] {
      self: List[A] =>
    }
    """
    val ast = treeFrom(str)
    var defdef: Tree = null

    topdown(matchingChildren(
      transform {
        case t: DefDef if (t.name == newTermName("enumerate")) =>
          defdef = t; t
      })) apply ast

    val names = Map("A" -> "A1")
    val res = topdown(matchingChildren(
      transform {
        case t @ TypeApply(Select(name, qualifier), args) =>
          val s = t.symbol.fullName
          val qual = s.substring(0, s.lastIndexOf("."))
          val select = Select(
            qualifier = Ident(name = newTypeName(qual)),
            name = t.fun.asInstanceOf[Select].name)
          t.copy(fun = select, args = args) setPos t.pos
        case t: TypeTree if (names.contains(t.nameString)) =>
          mkRenamedTypeTree(t, names(t.nameString).toString(), t.symbol)
        case t: TypeDef if (names.contains(t.name.toString)) =>
          mkRenamedSymTree(t, names(t.name.toString))
      })) apply defdef

    val result = topdown(matchingChildren(
      transform {
        case c: ClassDef if (c.name == newTypeName("tr")) =>
          val t = c.impl
          val templ = c.impl.copy(body = t.body ::: List(res.get)) setPos t.pos
          c.copy(impl = templ) setPos c.pos
      })) apply ast

    assertEquals("""
    package abc
    object primitive {
      def length[A](li:List[A]):Int = 0
      def enumerate[A](li:List[A]):List[Int] = {
        length[A](li)
      Nil
      }
    }
    trait tr[A] {
      self: List[A] =>
      def enumerate[A1](li:List[A1]):List[Int] = {
        abc.primitive.length[A1](li)
      Nil
      }
    }
    """, common.Change.applyChanges(refactor(result.toList), str))
  }
  
  @Test
  def changeMethodInvocation4() {

    val ast = treeFrom("""
    package abc
    object primitive {
      def append[A](li1: List[A], li2: List[A]) = Nil
      append(List("asd"), if(true) List("A") else List("B"))
    }
    """)

    val result = topdown {
      matchingChildren {
        transform {

          case a: Apply if (a.args.length > 1) =>
            val buf = a.args.toBuffer
            val arg = buf(1)
            buf.remove(1)
            val fun1 = Select(
              name = newTermName(a.fun.symbol.nameString),
              qualifier = arg)
            a.copy(args = buf.toList, fun = fun1) setPos a.pos
        }
      }
    } apply (ast)

    assertEquals("""
    package abc
    object primitive {
      def append[A](li1: List[A], li2: List[A]) = Nil
      (if(true) List("A") else List("B")).append(List("asd"))
    }
    """, createText(result.get, Some(ast.pos.source)))
  }
  
  @Test
  def changeMethodInvocation5() {

   val str = """
    package abc
    object primitive {
      def remove_if_not[A](fun:(A) => Boolean, li0:List[A]):List[A] = Nil
      val opentries = remove_if_not((_:List[Int]).isEmpty, List(Nil))
    }
    """
    val ast = treeFrom(str)

    val result = topdown {
      matchingChildren {
        transform {
          case a: Apply if (a.args.length > 1) =>
            val buf = a.args.toBuffer
            val arg = buf(1)
            buf.remove(1)
            val fun1 = Select(
              name = newTermName(a.fun.symbol.nameString),
              qualifier = arg)
            a.copy(args = buf.toList, fun = fun1) setPos a.pos
        case a: Function =>
          val res = topdown {
            matchingChildren {
              transform {
                case a: Apply =>
                  a.symbol = NoSymbol
                  a
              }
            }
          } apply a
          res.get
        }
      }
    } apply (ast)
    
    val changes = refactor(result.toList)
    val res = common.Change.applyChanges(changes, str)
    assertEquals("""
    package abc
    object primitive {
      def remove_if_not[A](fun:(A) => Boolean, li0:List[A]):List[A] = Nil
      val opentries = List(Nil).remove_if_not((_:List[Int]).isEmpty)
    }
    """, res)
  }

  @Test
  def patternMatchTest() {
    val src = """
  object acmatch {
    def fail = throw new UnsupportedOperationException("unsupported")
    def toInline() = if((null equals null)) true
      else fail
    def acmatch_expr(x: Any) = x match {
      case t: List[_] => toInline()
      case false => fail
    }
  }
    """
    val ast = treeFrom(src).asInstanceOf[PackageDef]
    val toInline = ast.stats(0).asInstanceOf[ModuleDef]
      .impl.body(2).asInstanceOf[DefDef]
    
    def mkPattern(varName: String, className: String, guard: Tree, rhs: Tree): CaseDef = {
      CaseDef(Bind(newTermName("t"),
        if (className != "") Typed(Ident(newTermName("")), Ident(newTermName(className)))
        else EmptyTree),
        guard, rhs)
    }
    
    val result = topdown {
      matchingChildren {
        transform {
          case t: Match =>
            val rhs = toInline.rhs.asInstanceOf[If]
            val caseDef = mkPattern("", "ASD", EmptyTree, rhs.copy())
            t.copy(cases = t.cases ::: List(caseDef))
          }
      }
    } apply ast
    assertEquals("""
  object acmatch {
    def fail = throw new UnsupportedOperationException("unsupported")
    def toInline() = if((null equals null)) true
      else fail
    def acmatch_expr(x: Any) = x match {
      case t: List[_] => toInline()
      case false => fail
      case t: ASD => if ((null equals null)) true else fail
    }
  }
    """, Change.applyChanges(refactor(result.toList), src))
  }
  
  @Test
  def patternMatchTest2() {
    val src = """
  object acmatch {
    def fail = throw new UnsupportedOperationException("unsupported")
    def method() {
    }
    class ASD
    def toInline() = {
      if (true && true) {
        if (!true) {
          fail
        } else {
          println("asd")
          if (true && true) true
          else false
        }
      } else method()
    }
    def acmatch_expr(x: Any) = x match {
      case false => fail
    }
  }
  """
    val ast = treeFrom(src).asInstanceOf[PackageDef]
    val toInline = ast.stats(0).asInstanceOf[ModuleDef]
      .impl.body(4).asInstanceOf[DefDef]

    def mkPattern(varName: String, className: String, guard: Tree, rhs: Tree): CaseDef = {
      CaseDef(Bind(newTermName("t"),
        if (className != "") Typed(Ident(newTermName("")), Ident(newTermName(className)))
        else EmptyTree),
        guard, rhs)
    }

    val result = topdown {
      matchingChildren {
        transform {
          case t: DefDef if(t.name.toString() == "acmatch_expr")=>
            val rhs = toInline.rhs.asInstanceOf[If]
            val caseDef = mkPattern("", "ASD", EmptyTree, rhs.copy())
            val matchx = Match(Ident(newTermName("x")), List(caseDef))
            t.copy(rhs = matchx) replaces t
        }
      }
    } apply ast
    assertEquals("""
  object acmatch {
    def fail = throw new UnsupportedOperationException("unsupported")
    def method() {
    }
    class ASD
    def toInline() = {
      if (true && true) {
        if (!true) {
          fail
        } else {
          println("asd")
          if (true && true) true
          else false
        }
      } else method()
    }
    def acmatch_expr(x: Any) = x match {
      case t: ASD => if (true && true) {
        if (!true) {
          fail
        } else {
          println("asd")
          if (true && true) true
          else false
        }
      } else method()
    }
  }
  """, Change.applyChanges(refactor(result.toList), src))
  }
  
  @Test
  def patternMatchTest3() {
    val src = """
object acmatch {
    def fail = throw new UnsupportedOperationException("unsupported")
    def subst_tlop2(obj: Expr, selfun1: (Expr) => Expr, selfun2: (Expr) => Expr): Expr = {
      null
    }
    def subst_until(obj: Expr): Expr = {
      subst_tlop2(obj, ((_: Expr).fma1), ((_: Expr).fma2))
    }

    def subst_expr(obj: Expr): Expr = {
      if (obj.untilp) subst_until(obj)
      else fail
    }
    abstract class Expr(val fma1: Expr, val fma2: Expr) {
      def untilp = false
    }
    abstract class Until(fma1: Expr, fma2: Expr) extends Expr(fma1, fma2) {
      override def untilp = true
    }
  }
  """
    val ast = treeFrom(src).asInstanceOf[PackageDef]
    val toInline = ast.stats(0).asInstanceOf[ModuleDef]
      .impl.body(3).asInstanceOf[DefDef]

    def mkPattern(varName: String, className: String, guard: Tree, rhs: Tree): CaseDef = {
      CaseDef(Bind(newTermName("t"),
        if (className != "") Typed(Ident(newTermName("")), Ident(newTermName(className)))
        else EmptyTree),
        guard, rhs)
    }

    val result = topdown {
      matchingChildren {
        transform {
          case t: DefDef if (t.name.toString() == "subst_expr") =>
            val rhs = toInline.rhs.asInstanceOf[Apply]
            val caseDef = mkPattern("", "Until", EmptyTree, rhs.copy())
            val matchx = Match(Ident(newTermName("obj")), List(caseDef))
            t.copy(rhs = matchx) setPos t.pos
        }
      }
    } apply ast
    assertEquals("""
object acmatch {
    def fail = throw new UnsupportedOperationException("unsupported")
    def subst_tlop2(obj: Expr, selfun1: (Expr) => Expr, selfun2: (Expr) => Expr): Expr = {
      null
    }
    def subst_until(obj: Expr): Expr = {
      subst_tlop2(obj, ((_: Expr).fma1), ((_: Expr).fma2))
    }

    def subst_expr(obj: Expr): Expr = obj match {
      case t: Until => subst_tlop2(obj, ((_: Expr).fma1), ((_: Expr).fma2))
    }
    abstract class Expr(val fma1: Expr, val fma2: Expr) {
      def untilp = false
    }
    abstract class Until(fma1: Expr, fma2: Expr) extends Expr(fma1, fma2) {
      override def untilp = true
    }
  }
  """, Change.applyChanges(refactor(result.toList), src))
  }
  
  @Test
  def patternMatchTest4() {
    val src = """
object acmatch {
    def fail = throw new UnsupportedOperationException("unsupported")
    def find[A](f: A => Boolean, li: List[A]) = li.head
    def compile_apply_substitution_on_abstractionmv(obj: Abstraction): (List[Mvmatch]) => Abstraction = {
      (subst: List[Mvmatch]) =>
        find((mvmatch: Mvmatch) => true, subst).abstractionmatchabstraction
    }
    def subst_expr(obj: Abstraction): (List[Mvmatch]) => Abstraction = {
      if (obj.abstractionmvp) compile_apply_substitution_on_abstractionmv(obj)
      else fail 
    }
    abstract class Abstraction {
      def abstractionmvp = false
    }
    class Abstractionmv extends Abstraction {
      override def abstractionmvp = true
    }
    class Mvmatch(val abstractionmatchmv: Abstraction, val abstractionmatchabstraction: Abstraction) {
      def abstractionmatchp = true
    }
  }
  """
    val ast = treeFrom(src).asInstanceOf[PackageDef]
    val toInline = ast.stats(0).asInstanceOf[ModuleDef]
      .impl.body(3).asInstanceOf[DefDef]

    def mkPattern(varName: String, className: String, guard: Tree, rhs: Tree): CaseDef = {
      CaseDef(Bind(newTermName("t"),
        if (className != "") Typed(Ident(newTermName("")), Ident(newTermName(className)))
        else EmptyTree),
        guard, rhs)
    }

    val result = topdown {
      matchingChildren {
        transform {
          case t: DefDef if (t.name.toString() == "subst_expr") =>
            val rhs = toInline.rhs.asInstanceOf[Function]
            val caseDef = mkPattern("", "Abstractionmv", EmptyTree, rhs.copy())
            val matchx = Match(Ident(newTermName("obj")), List(caseDef))
            t.copy(rhs = matchx) setPos t.pos
        }
      }
    } apply ast
    assertEquals("""
object acmatch {
    def fail = throw new UnsupportedOperationException("unsupported")
    def find[A](f: A => Boolean, li: List[A]) = li.head
    def compile_apply_substitution_on_abstractionmv(obj: Abstraction): (List[Mvmatch]) => Abstraction = {
      (subst: List[Mvmatch]) =>
        find((mvmatch: Mvmatch) => true, subst).abstractionmatchabstraction
    }
    def subst_expr(obj: Abstraction): (List[Mvmatch]) => Abstraction = obj match {
      case t: Abstractionmv => (subst: List[Mvmatch]) =>
      find((mvmatch: Mvmatch) => true, subst).abstractionmatchabstraction
    }
    abstract class Abstraction {
      def abstractionmvp = false
    }
    class Abstractionmv extends Abstraction {
      override def abstractionmvp = true
    }
    class Mvmatch(val abstractionmatchmv: Abstraction, val abstractionmatchabstraction: Abstraction) {
      def abstractionmatchp = true
    }
  }
  """, Change.applyChanges(refactor(result.toList), src))
  }
  
  @Test
  def changeMethodInvocation7() {

    val str = """
    package abc
    object primitive {
      def length[A](li: List[A]) = 0
      def reduce[A, B](li: List[B], fu: (A, B) => A, init: A): A = throw new Exception("ASD")
      def foo[A](li: List[Int], li2: List[Int]) = {  
        reduce(li, (a: Int, b: Int) => {
        length(li2) + b}, 0)
      }
    }
    """
    val ast = treeFrom(str)
    val result = topdown {
      matchingChildren {
        transform {
          case a @ Apply(fun: TypeApply, _) =>
            val buf = a.args.toBuffer
            val arg = buf(0)
            buf.remove(0)
            val fun1 = Select(
              name = newTermName(a.fun.symbol.nameString),
              qualifier = arg)
            a.copy(args = buf.toList, fun = fun1) setPos a.pos
        }
      }
    } apply (ast)
    val changes = refactor(result.toList)
    val res = Change.applyChanges(changes, str)
    assertEquals("""
    package abc
    object primitive {
      def length[A](li: List[A]) = 0
      def reduce[A, B](li: List[B], fu: (A, B) => A, init: A): A = throw new Exception("ASD")
      def foo[A](li: List[Int], li2: List[Int]) = {  
        li.reduce((a: Int, b: Int) => {
        li2.length() + b}, 0)
      }
    }
    """, res)
  }
  
  @Test
  def changeMethodInvocation8() {

    val str = """
    object primitive {
      def reduce[A, B](fu: (A, B) => A, li: List[B], init: A): A = init
      def asd(li: List[Int]) = {
        reduce(((_:Int) + (_:Int)),li, 0) 
      }
    }
    """
    val ast = treeFrom(str)

    val result = topdown {
      matchingChildren {
        transform {
          case a: Apply if (a.args.length > 1) =>
            val buf = a.args.toBuffer
            val arg = buf(1)
            buf.remove(1)
            val fun1 = Select(
              name = newTermName(a.fun.symbol.nameString),
              qualifier = arg)
            a.copy(args = buf.toList, fun = fun1) setPos a.pos
        }
      }
    } apply (ast)

    val changes = refactor(result.toList)
    val res = Change.applyChanges(changes, str)
    assertEquals("""
    object primitive {
      def reduce[A, B](fu: (A, B) => A, li: List[B], init: A): A = init
      def asd(li: List[Int]) = {
        li.reduce((_:Int) + (_:Int), 0) 
      }
    }
    """, res)
  }
    
  @Test
  def testAddSealed() {
    val str = """
    abstract class asd {
    }
    class XY
    """
    val ast = treeFrom(str)
    val res = once {
      transform {
        case t: PackageDef =>
          val st = t.stats.map(a => a match {
            case x: ClassDef =>
              x.copy(mods = x.mods.withPosition(Flags.SEALED, NoPosition)) setPos x.pos
            case x => x
          })
          t.copy(stats = st) setPos t.pos
      }} apply ast

    assertEquals("""
    abstract sealed class asd {
    }
    sealed class XY
    """, Change.applyChanges(refactor(res.toList), str))
  }
  
  @Test
  def testRemoveSealed() {
    val str = """
    abstract sealed class asd {
    }
    sealed class XY
    """
    val ast = treeFrom(str)
    val res = topdown {
      matchingChildren {
        transform {
          case x: ClassDef => x.copy(mods = NoMods) replaces x
        }
      }
     } apply ast

    assertEquals("""
    class asd {
    }
    class XY
    """, Change.applyChanges(refactor(res.toList), str))
  }
      
  @Test
  def testAddSealedPP() {
    val str = """
    abstract class asd {
    }
    class XY
    """
    val ast = treeFrom(str)
    val res = once {
      transform {
        case t: PackageDef =>
          val st = t.stats.map(a => a match {
            case x: ClassDef =>
              x.copy(mods = x.mods.withPosition(Flags.SEALED, NoPosition))
            case x => x
          })
          t.copy(stats = st) setPos t.pos
      }} apply ast

    assertEquals("""
    abstract sealed class asd {
    }
    
    sealed class XY
    """, Change.applyChanges(refactor(res.toList), str))
  }
  
  @Test
  def testRemoveSealedPP() {
    val str = """
    abstract sealed class asd {
    }
    sealed class XY
    """
    val ast = treeFrom(str)
    val res = topdown {
      matchingChildren {
        transform {
          case x: ClassDef => x.copy(mods = NoMods)
        }
      }
     } apply ast

    assertEquals("""
    class asd {
    }
    
    class XY
    """, Change.applyChanges(refactor(res.toList), str))
  }
}