[groovy] extract findDeclaredDetachedValue() to utility file
[idea/community.git] / plugins / groovy / groovy-psi / src / org / jetbrains / plugins / groovy / transformations / impl / autoClone / AutoCloneTransformationSupport.kt
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.plugins.groovy.transformations.impl.autoClone
17
18 import com.intellij.psi.CommonClassNames
19 import com.intellij.psi.PsiEnumConstant
20 import com.intellij.psi.PsiModifier
21 import com.intellij.psi.PsiType
22 import com.intellij.psi.impl.light.LightMethodBuilder
23 import org.jetbrains.plugins.groovy.GroovyLanguage
24 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression
25 import org.jetbrains.plugins.groovy.lang.psi.impl.findDeclaredDetachedValue
26 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil
27 import org.jetbrains.plugins.groovy.transformations.AstTransformationSupport
28 import org.jetbrains.plugins.groovy.transformations.TransformationContext
29 import org.jetbrains.plugins.groovy.transformations.plusAssign
30
31 class AutoCloneTransformationSupport : AstTransformationSupport {
32
33   private companion object {
34     val AUTO_CLONE_FQN = "groovy.transform.AutoClone"
35     val ORIGIN_INFO = "created by @AutoClone"
36     val CNSE_FQN = "java.lang.CloneNotSupportedException"
37   }
38
39   override fun applyTransformation(context: TransformationContext) {
40     val annotation = context.getAnnotation(AUTO_CLONE_FQN) ?: return
41
42     context.addInterface(CommonClassNames.JAVA_LANG_CLONEABLE)
43
44     // public T clone() throws CloneNotSupportedException
45     context += LightMethodBuilder(context.manager, "clone").apply {
46       addModifier(PsiModifier.PUBLIC)
47       setMethodReturnType(TypesUtil.createType(context.codeClass))
48       addException(CNSE_FQN)
49       navigationElement = annotation
50       originInfo = ORIGIN_INFO
51     }
52
53     val value = annotation.findDeclaredDetachedValue("style") as? GrReferenceExpression ?: return
54     val constant = value.resolve() as? PsiEnumConstant ?: return
55     if (constant.containingClass?.qualifiedName != "groovy.transform.AutoCloneStyle") return
56     when (constant.name) {
57       "COPY_CONSTRUCTOR" -> {
58         if (context.codeClass.codeConstructors.isEmpty()) {
59           context += LightMethodBuilder(context.codeClass, GroovyLanguage).apply {
60             isConstructor = true
61             addModifier(PsiModifier.PUBLIC)
62             navigationElement = context.codeClass
63           }
64         }
65
66         // protected T(T other)
67         context += LightMethodBuilder(context.codeClass, GroovyLanguage).apply {
68           isConstructor = true
69           addModifier(PsiModifier.PROTECTED)
70           addParameter("other", TypesUtil.createType(context.codeClass))
71           navigationElement = context.codeClass
72           originInfo = ORIGIN_INFO
73         }
74       }
75       "SIMPLE" -> {
76         // protected void cloneOrCopyMembers(T other) throws CloneNotSupportedException
77         context += LightMethodBuilder(context.manager, "cloneOrCopyMembers").apply {
78           addModifier(PsiModifier.PROTECTED)
79           setMethodReturnType(PsiType.VOID)
80           addParameter("other", TypesUtil.createType(context.codeClass))
81           addException(CNSE_FQN)
82           navigationElement = annotation
83           originInfo = ORIGIN_INFO
84         }
85       }
86     }
87   }
88 }