@@ -10,30 +10,66 @@ abstract class ImplementMethods extends MultiStageRefactoring with analysis.Inde
1010
1111 case class PreparationResult (targetTemplate : Template , methodsToImplement : Seq [DefDef ])
1212
13+ /* Helper class to box methods so they can be
14+ compared in terms of their signature.
15+ */
16+ implicit class OverloadedMethod (val method : DefDef ) {
17+
18+ private val key = {
19+ import method .{name , tparams , vparamss }
20+
21+ val vparamsTypes = for {
22+ paramList <- vparamss
23+ param <- paramList
24+ } yield param.tpt.tpe
25+
26+ (name, tparams, vparamsTypes)
27+
28+ }
29+
30+ override def hashCode (): RunId = key.hashCode()
31+
32+ override def equals (obj : scala.Any ): Boolean = obj match {
33+ case that : OverloadedMethod => key == that.key
34+ case _ => false
35+ }
36+ }
37+
1338 override def prepare (s : Selection ): Either [PreparationError , PreparationResult ] = {
1439
40+ // Get a sequence of methods found in the selected mixed trait.
1541 val methodsToImplement = for {
1642 selectedTemplateDeclaration <- index.declaration(s.enclosingTree.symbol).toSeq collect {
17- case traitDeclaration : ClassDef => traitDeclaration
43+ case templateDeclaration : ClassDef => templateDeclaration
1844 }
1945 unimplementedMethod <- selectedTemplateDeclaration.impl.body collect {
20- case methodDeclaration : DefDef if methodDeclaration.rhs.isEmpty => methodDeclaration
46+ case methodDeclaration : DefDef if methodDeclaration.rhs.isEmpty =>
47+ methodDeclaration
2148 }
2249 } yield unimplementedMethod
2350
51+ // Use the selection to find the template where the methods should be implemented.
2452 val targetTemplate = s.expandToNextEnclosingTree.flatMap {
2553 _.selectedSymbolTree collect {
2654 case target : Template => target
2755 }
2856 }
2957
30- if (targetTemplate.isEmpty) Left {
58+ targetTemplate map { t => // If the selection has indeed a target template...
59+ if (methodsToImplement.isEmpty) Left { // ... as long as there are methods in the mixed trait...
60+ PreparationError (" There are not methods to implement" )
61+ } else Right { // ... these are selected to be defined in the target template.
62+ // If and only if they're not already defined there.
63+ val implementedMethods : Set [OverloadedMethod ] = {
64+ t.body collect {
65+ case methodDef : DefDef => new OverloadedMethod (methodDef)
66+ } toSet
67+ }
68+ PreparationResult (t, methodsToImplement.filterNot(implementedMethods contains _))
69+ }
70+ } getOrElse Left {
3171 PreparationError (" No target class in selection" )
3272 }
33- else if (methodsToImplement.isEmpty) Left {
34- PreparationError (" There are not methods to implement" )
35- }
36- else Right (PreparationResult (targetTemplate.get, methodsToImplement))
3773 }
3874
3975 override type RefactoringParameters = Unit
0 commit comments